s_texcombine.c revision 7117f1b4
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.1
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#include "glheader.h"
27#include "context.h"
28#include "colormac.h"
29#include "imports.h"
30#include "macros.h"
31#include "pixel.h"
32
33#include "s_context.h"
34#include "s_texcombine.h"
35
36
37#define PROD(A,B)   ( (GLuint)(A) * ((GLuint)(B)+1) )
38#define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
39#if CHAN_BITS == 32
40typedef GLfloat ChanTemp;
41#else
42typedef GLuint ChanTemp;
43#endif
44
45
46/**
47 * Do texture application for GL_ARB/EXT_texture_env_combine.
48 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
49 * GL_ATI_texture_env_combine3.  Since "classic" texture environments are
50 * implemented using GL_ARB_texture_env_combine-like state, this same function
51 * is used for classic texture environment application as well.
52 *
53 * \param ctx          rendering context
54 * \param textureUnit  the texture unit to apply
55 * \param n            number of fragments to process (span width)
56 * \param primary_rgba incoming fragment color array
57 * \param texelBuffer  pointer to texel colors for all texture units
58 *
59 * \param rgba         incoming colors, which get modified here
60 */
61static void
62texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
63                 CONST GLchan (*primary_rgba)[4],
64                 CONST GLchan *texelBuffer,
65                 GLchan (*rgba)[4] )
66{
67   const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
68   const GLchan (*argRGB [3])[4];
69   const GLchan (*argA [3])[4];
70   const GLuint RGBshift = textureUnit->_CurrentCombine->ScaleShiftRGB;
71   const GLuint Ashift   = textureUnit->_CurrentCombine->ScaleShiftA;
72#if CHAN_TYPE == GL_FLOAT
73   const GLchan RGBmult = (GLfloat) (1 << RGBshift);
74   const GLchan Amult = (GLfloat) (1 << Ashift);
75#else
76   const GLint half = (CHAN_MAX + 1) / 2;
77#endif
78   static const GLchan one[4] = { CHAN_MAX, CHAN_MAX, CHAN_MAX, CHAN_MAX };
79   static const GLchan zero[4] = { 0, 0, 0, 0 };
80   const GLuint numColorArgs = textureUnit->_CurrentCombine->_NumArgsRGB;
81   const GLuint numAlphaArgs = textureUnit->_CurrentCombine->_NumArgsA;
82   GLchan ccolor[3][MAX_WIDTH][4];
83   GLuint i, j;
84
85   ASSERT(ctx->Extensions.EXT_texture_env_combine ||
86          ctx->Extensions.ARB_texture_env_combine);
87   ASSERT(SWRAST_CONTEXT(ctx)->_AnyTextureCombine);
88
89   /*
90   printf("modeRGB 0x%x  modeA 0x%x  srcRGB1 0x%x  srcA1 0x%x  srcRGB2 0x%x  srcA2 0x%x\n",
91          textureUnit->_CurrentCombine->ModeRGB,
92          textureUnit->_CurrentCombine->ModeA,
93          textureUnit->_CurrentCombine->SourceRGB[0],
94          textureUnit->_CurrentCombine->SourceA[0],
95          textureUnit->_CurrentCombine->SourceRGB[1],
96          textureUnit->_CurrentCombine->SourceA[1]);
97   */
98
99   /*
100    * Do operand setup for up to 3 operands.  Loop over the terms.
101    */
102   for (j = 0; j < numColorArgs; j++) {
103      const GLenum srcRGB = textureUnit->_CurrentCombine->SourceRGB[j];
104
105      switch (srcRGB) {
106         case GL_TEXTURE:
107            argRGB[j] = (const GLchan (*)[4])
108               (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
109            break;
110         case GL_PRIMARY_COLOR:
111            argRGB[j] = primary_rgba;
112            break;
113         case GL_PREVIOUS:
114            argRGB[j] = (const GLchan (*)[4]) rgba;
115            break;
116         case GL_CONSTANT:
117            {
118               GLchan (*c)[4] = ccolor[j];
119               GLchan red, green, blue, alpha;
120               UNCLAMPED_FLOAT_TO_CHAN(red,   textureUnit->EnvColor[0]);
121               UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
122               UNCLAMPED_FLOAT_TO_CHAN(blue,  textureUnit->EnvColor[2]);
123               UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
124               for (i = 0; i < n; i++) {
125                  c[i][RCOMP] = red;
126                  c[i][GCOMP] = green;
127                  c[i][BCOMP] = blue;
128                  c[i][ACOMP] = alpha;
129               }
130               argRGB[j] = (const GLchan (*)[4]) ccolor[j];
131            }
132            break;
133	 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
134	  */
135	 case GL_ZERO:
136            argRGB[j] = & zero;
137            break;
138	 case GL_ONE:
139            argRGB[j] = & one;
140            break;
141         default:
142            /* ARB_texture_env_crossbar source */
143            {
144               const GLuint srcUnit = srcRGB - GL_TEXTURE0;
145               ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
146               if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
147                  return;
148               argRGB[j] = (const GLchan (*)[4])
149                  (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
150            }
151      }
152
153      if (textureUnit->_CurrentCombine->OperandRGB[j] != GL_SRC_COLOR) {
154         const GLchan (*src)[4] = argRGB[j];
155         GLchan (*dst)[4] = ccolor[j];
156
157         /* point to new arg[j] storage */
158         argRGB[j] = (const GLchan (*)[4]) ccolor[j];
159
160         if (textureUnit->_CurrentCombine->OperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
161            for (i = 0; i < n; i++) {
162               dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
163               dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
164               dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
165            }
166         }
167         else if (textureUnit->_CurrentCombine->OperandRGB[j] == GL_SRC_ALPHA) {
168            for (i = 0; i < n; i++) {
169               dst[i][RCOMP] = src[i][ACOMP];
170               dst[i][GCOMP] = src[i][ACOMP];
171               dst[i][BCOMP] = src[i][ACOMP];
172            }
173         }
174         else {
175            ASSERT(textureUnit->_CurrentCombine->OperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
176            for (i = 0; i < n; i++) {
177               dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
178               dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
179               dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
180            }
181         }
182      }
183   }
184
185   /*
186    * Set up the argA[i] pointers
187    */
188   for (j = 0; j < numAlphaArgs; j++) {
189      const GLenum srcA = textureUnit->_CurrentCombine->SourceA[j];
190
191      switch (srcA) {
192         case GL_TEXTURE:
193            argA[j] = (const GLchan (*)[4])
194               (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
195            break;
196         case GL_PRIMARY_COLOR:
197            argA[j] = primary_rgba;
198            break;
199         case GL_PREVIOUS:
200            argA[j] = (const GLchan (*)[4]) rgba;
201            break;
202         case GL_CONSTANT:
203            {
204               GLchan alpha, (*c)[4] = ccolor[j];
205               UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
206               for (i = 0; i < n; i++)
207                  c[i][ACOMP] = alpha;
208               argA[j] = (const GLchan (*)[4]) ccolor[j];
209            }
210            break;
211	 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
212	  */
213	 case GL_ZERO:
214            argA[j] = & zero;
215            break;
216	 case GL_ONE:
217            argA[j] = & one;
218            break;
219         default:
220            /* ARB_texture_env_crossbar source */
221            {
222               const GLuint srcUnit = srcA - GL_TEXTURE0;
223               ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
224               if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
225                  return;
226               argA[j] = (const GLchan (*)[4])
227                  (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
228            }
229      }
230
231      if (textureUnit->_CurrentCombine->OperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
232         const GLchan (*src)[4] = argA[j];
233         GLchan (*dst)[4] = ccolor[j];
234         argA[j] = (const GLchan (*)[4]) ccolor[j];
235         for (i = 0; i < n; i++) {
236            dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
237         }
238      }
239   }
240
241   /*
242    * Do the texture combine.
243    */
244   switch (textureUnit->_CurrentCombine->ModeRGB) {
245      case GL_REPLACE:
246         {
247            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
248            if (RGBshift) {
249               for (i = 0; i < n; i++) {
250#if CHAN_TYPE == GL_FLOAT
251                  rgba[i][RCOMP] = arg0[i][RCOMP] * RGBmult;
252                  rgba[i][GCOMP] = arg0[i][GCOMP] * RGBmult;
253                  rgba[i][BCOMP] = arg0[i][BCOMP] * RGBmult;
254#else
255                  GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
256                  GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
257                  GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
258                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
259                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
260                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
261#endif
262               }
263            }
264            else {
265               for (i = 0; i < n; i++) {
266                  rgba[i][RCOMP] = arg0[i][RCOMP];
267                  rgba[i][GCOMP] = arg0[i][GCOMP];
268                  rgba[i][BCOMP] = arg0[i][BCOMP];
269               }
270            }
271         }
272         break;
273      case GL_MODULATE:
274         {
275            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
276            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
277#if CHAN_TYPE != GL_FLOAT
278            const GLint shift = CHAN_BITS - RGBshift;
279#endif
280            for (i = 0; i < n; i++) {
281#if CHAN_TYPE == GL_FLOAT
282               rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * RGBmult;
283               rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * RGBmult;
284               rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * RGBmult;
285#else
286               GLuint r = PROD(arg0[i][RCOMP], arg1[i][RCOMP]) >> shift;
287               GLuint g = PROD(arg0[i][GCOMP], arg1[i][GCOMP]) >> shift;
288               GLuint b = PROD(arg0[i][BCOMP], arg1[i][BCOMP]) >> shift;
289               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
290               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
291               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
292#endif
293            }
294         }
295         break;
296      case GL_ADD:
297         {
298            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
299            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
300            for (i = 0; i < n; i++) {
301#if CHAN_TYPE == GL_FLOAT
302               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * RGBmult;
303               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * RGBmult;
304               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * RGBmult;
305#else
306               GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
307               GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
308               GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
309               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
310               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
311               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
312#endif
313            }
314         }
315         break;
316      case GL_ADD_SIGNED:
317         {
318            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
319            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
320            for (i = 0; i < n; i++) {
321#if CHAN_TYPE == GL_FLOAT
322               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * RGBmult;
323               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * RGBmult;
324               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * RGBmult;
325#else
326               GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] -half;
327               GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] -half;
328               GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] -half;
329               r = (r < 0) ? 0 : r << RGBshift;
330               g = (g < 0) ? 0 : g << RGBshift;
331               b = (b < 0) ? 0 : b << RGBshift;
332               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
333               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
334               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
335#endif
336            }
337         }
338         break;
339      case GL_INTERPOLATE:
340         {
341            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
342            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
343            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
344#if CHAN_TYPE != GL_FLOAT
345            const GLint shift = CHAN_BITS - RGBshift;
346#endif
347            for (i = 0; i < n; i++) {
348#if CHAN_TYPE == GL_FLOAT
349               rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
350                      arg1[i][RCOMP] * (CHAN_MAXF - arg2[i][RCOMP])) * RGBmult;
351               rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
352                      arg1[i][GCOMP] * (CHAN_MAXF - arg2[i][GCOMP])) * RGBmult;
353               rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
354                      arg1[i][BCOMP] * (CHAN_MAXF - arg2[i][BCOMP])) * RGBmult;
355#else
356               GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
357                           + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
358                              >> shift;
359               GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
360                           + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
361                              >> shift;
362               GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
363                           + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
364                              >> shift;
365               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
366               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
367               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
368#endif
369            }
370         }
371         break;
372      case GL_SUBTRACT:
373         {
374            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
375            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
376            for (i = 0; i < n; i++) {
377#if CHAN_TYPE == GL_FLOAT
378               rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * RGBmult;
379               rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * RGBmult;
380               rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * RGBmult;
381#else
382               GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
383               GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
384               GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
385               rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
386               rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
387               rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
388#endif
389            }
390         }
391         break;
392      case GL_DOT3_RGB_EXT:
393      case GL_DOT3_RGBA_EXT:
394         {
395            /* Do not scale the result by 1 2 or 4 */
396            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
397            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
398            for (i = 0; i < n; i++) {
399#if CHAN_TYPE == GL_FLOAT
400               GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
401                             (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
402                             (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
403                            * 4.0F;
404               dot = CLAMP(dot, 0.0F, CHAN_MAXF);
405#else
406               GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
407				   (GLint)arg1[i][RCOMP] - half) +
408			    S_PROD((GLint)arg0[i][GCOMP] - half,
409				   (GLint)arg1[i][GCOMP] - half) +
410			    S_PROD((GLint)arg0[i][BCOMP] - half,
411				   (GLint)arg1[i][BCOMP] - half)) >> 6;
412               dot = CLAMP(dot, 0, CHAN_MAX);
413#endif
414               rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
415            }
416         }
417         break;
418      case GL_DOT3_RGB:
419      case GL_DOT3_RGBA:
420         {
421            /* DO scale the result by 1 2 or 4 */
422            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
423            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
424            for (i = 0; i < n; i++) {
425#if CHAN_TYPE == GL_FLOAT
426               GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
427                             (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
428                             (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
429                            * 4.0F * RGBmult;
430               dot = CLAMP(dot, 0.0, CHAN_MAXF);
431#else
432               GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
433				   (GLint)arg1[i][RCOMP] - half) +
434			    S_PROD((GLint)arg0[i][GCOMP] - half,
435				   (GLint)arg1[i][GCOMP] - half) +
436			    S_PROD((GLint)arg0[i][BCOMP] - half,
437				   (GLint)arg1[i][BCOMP] - half)) >> 6;
438               dot <<= RGBshift;
439               dot = CLAMP(dot, 0, CHAN_MAX);
440#endif
441               rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
442            }
443         }
444         break;
445      case GL_MODULATE_ADD_ATI:
446         {
447            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
448            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
449            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
450#if CHAN_TYPE != GL_FLOAT
451            const GLint shift = CHAN_BITS - RGBshift;
452#endif
453            for (i = 0; i < n; i++) {
454#if CHAN_TYPE == GL_FLOAT
455               rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP]) * RGBmult;
456               rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP]) * RGBmult;
457               rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP]) * RGBmult;
458#else
459               GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
460                           + ((GLuint) arg1[i][RCOMP] << CHAN_BITS)) >> shift;
461               GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
462                           + ((GLuint) arg1[i][GCOMP] << CHAN_BITS)) >> shift;
463               GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
464                           + ((GLuint) arg1[i][BCOMP] << CHAN_BITS)) >> shift;
465               rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
466               rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
467               rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
468#endif
469            }
470	 }
471         break;
472      case GL_MODULATE_SIGNED_ADD_ATI:
473         {
474            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
475            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
476            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
477#if CHAN_TYPE != GL_FLOAT
478            const GLint shift = CHAN_BITS - RGBshift;
479#endif
480            for (i = 0; i < n; i++) {
481#if CHAN_TYPE == GL_FLOAT
482               rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP] - 0.5) * RGBmult;
483               rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP] - 0.5) * RGBmult;
484               rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP] - 0.5) * RGBmult;
485#else
486               GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP])
487			  + (((GLint) arg1[i][RCOMP] - half) << CHAN_BITS))
488		    >> shift;
489               GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP])
490			  + (((GLint) arg1[i][GCOMP] - half) << CHAN_BITS))
491		    >> shift;
492               GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP])
493			  + (((GLint) arg1[i][BCOMP] - half) << CHAN_BITS))
494		    >> shift;
495               rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
496               rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
497               rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
498#endif
499            }
500	 }
501         break;
502      case GL_MODULATE_SUBTRACT_ATI:
503         {
504            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
505            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
506            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
507#if CHAN_TYPE != GL_FLOAT
508            const GLint shift = CHAN_BITS - RGBshift;
509#endif
510            for (i = 0; i < n; i++) {
511#if CHAN_TYPE == GL_FLOAT
512               rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) - arg1[i][RCOMP]) * RGBmult;
513               rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) - arg1[i][GCOMP]) * RGBmult;
514               rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) - arg1[i][BCOMP]) * RGBmult;
515#else
516               GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP])
517			  - ((GLint) arg1[i][RCOMP] << CHAN_BITS))
518		    >> shift;
519               GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP])
520			  - ((GLint) arg1[i][GCOMP] << CHAN_BITS))
521		    >> shift;
522               GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP])
523			  - ((GLint) arg1[i][BCOMP] << CHAN_BITS))
524		    >> shift;
525               rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
526               rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
527               rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
528#endif
529            }
530	 }
531         break;
532      default:
533         _mesa_problem(ctx, "invalid combine mode");
534   }
535
536   switch (textureUnit->_CurrentCombine->ModeA) {
537      case GL_REPLACE:
538         {
539            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
540            if (Ashift) {
541               for (i = 0; i < n; i++) {
542#if CHAN_TYPE == GL_FLOAT
543                  GLchan a = arg0[i][ACOMP] * Amult;
544#else
545                  GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
546#endif
547                  rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
548               }
549            }
550            else {
551               for (i = 0; i < n; i++) {
552                  rgba[i][ACOMP] = arg0[i][ACOMP];
553               }
554            }
555         }
556         break;
557      case GL_MODULATE:
558         {
559            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
560            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
561#if CHAN_TYPE != GL_FLOAT
562            const GLint shift = CHAN_BITS - Ashift;
563#endif
564            for (i = 0; i < n; i++) {
565#if CHAN_TYPE == GL_FLOAT
566               rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * Amult;
567#else
568               GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
569               rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
570#endif
571            }
572         }
573         break;
574      case GL_ADD:
575         {
576            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
577            const GLchan  (*arg1)[4] = (const GLchan (*)[4]) argA[1];
578            for (i = 0; i < n; i++) {
579#if CHAN_TYPE == GL_FLOAT
580               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * Amult;
581#else
582               GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
583               rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
584#endif
585            }
586         }
587         break;
588      case GL_ADD_SIGNED:
589         {
590            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
591            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
592            for (i = 0; i < n; i++) {
593#if CHAN_TYPE == GL_FLOAT
594               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * Amult;
595#else
596               GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] -half;
597               a = (a < 0) ? 0 : a << Ashift;
598               rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
599#endif
600            }
601         }
602         break;
603      case GL_INTERPOLATE:
604         {
605            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
606            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
607            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
608#if CHAN_TYPE != GL_FLOAT
609            const GLint shift = CHAN_BITS - Ashift;
610#endif
611            for (i=0; i<n; i++) {
612#if CHAN_TYPE == GL_FLOAT
613               rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
614                                 arg1[i][ACOMP] * (CHAN_MAXF - arg2[i][ACOMP]))
615                                * Amult;
616#else
617               GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
618                           + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
619                              >> shift;
620               rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
621#endif
622            }
623         }
624         break;
625      case GL_SUBTRACT:
626         {
627            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
628            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
629            for (i = 0; i < n; i++) {
630#if CHAN_TYPE == GL_FLOAT
631               rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * Amult;
632#else
633               GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << Ashift;
634               rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
635#endif
636            }
637         }
638         break;
639      case GL_MODULATE_ADD_ATI:
640         {
641            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
642            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
643            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
644#if CHAN_TYPE != GL_FLOAT
645            const GLint shift = CHAN_BITS - Ashift;
646#endif
647            for (i = 0; i < n; i++) {
648#if CHAN_TYPE == GL_FLOAT
649               rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP]) * Amult;
650#else
651               GLint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
652			   + ((GLuint) arg1[i][ACOMP] << CHAN_BITS))
653		    >> shift;
654               rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
655#endif
656            }
657         }
658         break;
659      case GL_MODULATE_SIGNED_ADD_ATI:
660         {
661            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
662            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
663            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
664#if CHAN_TYPE != GL_FLOAT
665            const GLint shift = CHAN_BITS - Ashift;
666#endif
667            for (i = 0; i < n; i++) {
668#if CHAN_TYPE == GL_FLOAT
669               rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP] - 0.5F) * Amult;
670#else
671               GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP])
672			  + (((GLint) arg1[i][ACOMP] - half) << CHAN_BITS))
673		    >> shift;
674               rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
675#endif
676            }
677         }
678         break;
679      case GL_MODULATE_SUBTRACT_ATI:
680         {
681            const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
682            const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
683            const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
684#if CHAN_TYPE != GL_FLOAT
685            const GLint shift = CHAN_BITS - Ashift;
686#endif
687            for (i = 0; i < n; i++) {
688#if CHAN_TYPE == GL_FLOAT
689               rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) - arg1[i][ACOMP]) * Amult;
690#else
691               GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP])
692			  - ((GLint) arg1[i][ACOMP] << CHAN_BITS))
693		    >> shift;
694               rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
695#endif
696            }
697         }
698         break;
699      default:
700         _mesa_problem(ctx, "invalid combine mode");
701   }
702
703   /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
704    * This is kind of a kludge.  It would have been better if the spec
705    * were written such that the GL_COMBINE_ALPHA value could be set to
706    * GL_DOT3.
707    */
708   if (textureUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT ||
709       textureUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) {
710      for (i = 0; i < n; i++) {
711	 rgba[i][ACOMP] = rgba[i][RCOMP];
712      }
713   }
714}
715#undef PROD
716
717
718/**
719 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
720 * MODULATE, or DECAL) to an array of fragments.
721 * Input:  textureUnit - pointer to texture unit to apply
722 *         format - base internal texture format
723 *         n - number of fragments
724 *         primary_rgba - primary colors (may alias rgba for single texture)
725 *         texels - array of texel colors
726 * InOut:  rgba - incoming fragment colors modified by texel colors
727 *                according to the texture environment mode.
728 */
729static void
730texture_apply( const GLcontext *ctx,
731               const struct gl_texture_unit *texUnit,
732               GLuint n,
733               CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
734               GLchan rgba[][4] )
735{
736   GLint baseLevel;
737   GLuint i;
738   GLchan Rc, Gc, Bc, Ac;
739   GLenum format;
740   (void) primary_rgba;
741
742   ASSERT(texUnit);
743   ASSERT(texUnit->_Current);
744
745   baseLevel = texUnit->_Current->BaseLevel;
746   ASSERT(texUnit->_Current->Image[0][baseLevel]);
747
748   format = texUnit->_Current->Image[0][baseLevel]->_BaseFormat;
749
750   if (format == GL_COLOR_INDEX || format == GL_YCBCR_MESA) {
751      format = GL_RGBA;  /* a bit of a hack */
752   }
753   else if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
754      format = texUnit->_Current->DepthMode;
755   }
756
757   switch (texUnit->EnvMode) {
758      case GL_REPLACE:
759	 switch (format) {
760	    case GL_ALPHA:
761	       for (i=0;i<n;i++) {
762		  /* Cv = Cf */
763                  /* Av = At */
764                  rgba[i][ACOMP] = texel[i][ACOMP];
765	       }
766	       break;
767	    case GL_LUMINANCE:
768	       for (i=0;i<n;i++) {
769		  /* Cv = Lt */
770                  GLchan Lt = texel[i][RCOMP];
771                  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
772                  /* Av = Af */
773	       }
774	       break;
775	    case GL_LUMINANCE_ALPHA:
776	       for (i=0;i<n;i++) {
777                  GLchan Lt = texel[i][RCOMP];
778		  /* Cv = Lt */
779		  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
780		  /* Av = At */
781		  rgba[i][ACOMP] = texel[i][ACOMP];
782	       }
783	       break;
784	    case GL_INTENSITY:
785	       for (i=0;i<n;i++) {
786		  /* Cv = It */
787                  GLchan It = texel[i][RCOMP];
788                  rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
789                  /* Av = It */
790                  rgba[i][ACOMP] = It;
791	       }
792	       break;
793	    case GL_RGB:
794	       for (i=0;i<n;i++) {
795		  /* Cv = Ct */
796		  rgba[i][RCOMP] = texel[i][RCOMP];
797		  rgba[i][GCOMP] = texel[i][GCOMP];
798		  rgba[i][BCOMP] = texel[i][BCOMP];
799		  /* Av = Af */
800	       }
801	       break;
802	    case GL_RGBA:
803	       for (i=0;i<n;i++) {
804		  /* Cv = Ct */
805		  rgba[i][RCOMP] = texel[i][RCOMP];
806		  rgba[i][GCOMP] = texel[i][GCOMP];
807		  rgba[i][BCOMP] = texel[i][BCOMP];
808		  /* Av = At */
809		  rgba[i][ACOMP] = texel[i][ACOMP];
810	       }
811	       break;
812            default:
813               _mesa_problem(ctx, "Bad format (GL_REPLACE) in texture_apply");
814               return;
815	 }
816	 break;
817
818      case GL_MODULATE:
819         switch (format) {
820	    case GL_ALPHA:
821	       for (i=0;i<n;i++) {
822		  /* Cv = Cf */
823		  /* Av = AfAt */
824		  rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
825	       }
826	       break;
827	    case GL_LUMINANCE:
828	       for (i=0;i<n;i++) {
829		  /* Cv = LtCf */
830                  GLchan Lt = texel[i][RCOMP];
831		  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
832		  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
833		  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
834		  /* Av = Af */
835	       }
836	       break;
837	    case GL_LUMINANCE_ALPHA:
838	       for (i=0;i<n;i++) {
839		  /* Cv = CfLt */
840                  GLchan Lt = texel[i][RCOMP];
841		  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
842		  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
843		  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
844		  /* Av = AfAt */
845		  rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
846	       }
847	       break;
848	    case GL_INTENSITY:
849	       for (i=0;i<n;i++) {
850		  /* Cv = CfIt */
851                  GLchan It = texel[i][RCOMP];
852		  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
853		  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
854		  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
855		  /* Av = AfIt */
856		  rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
857	       }
858	       break;
859	    case GL_RGB:
860	       for (i=0;i<n;i++) {
861		  /* Cv = CfCt */
862		  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
863		  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
864		  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
865		  /* Av = Af */
866	       }
867	       break;
868	    case GL_RGBA:
869	       for (i=0;i<n;i++) {
870		  /* Cv = CfCt */
871		  rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
872		  rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
873		  rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
874		  /* Av = AfAt */
875		  rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
876	       }
877	       break;
878            default:
879               _mesa_problem(ctx, "Bad format (GL_MODULATE) in texture_apply");
880               return;
881	 }
882	 break;
883
884      case GL_DECAL:
885         switch (format) {
886            case GL_ALPHA:
887            case GL_LUMINANCE:
888            case GL_LUMINANCE_ALPHA:
889            case GL_INTENSITY:
890               /* undefined */
891               break;
892	    case GL_RGB:
893	       for (i=0;i<n;i++) {
894		  /* Cv = Ct */
895		  rgba[i][RCOMP] = texel[i][RCOMP];
896		  rgba[i][GCOMP] = texel[i][GCOMP];
897		  rgba[i][BCOMP] = texel[i][BCOMP];
898		  /* Av = Af */
899	       }
900	       break;
901	    case GL_RGBA:
902	       for (i=0;i<n;i++) {
903		  /* Cv = Cf(1-At) + CtAt */
904		  GLchan t = texel[i][ACOMP], s = CHAN_MAX - t;
905		  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
906		  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
907		  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
908		  /* Av = Af */
909	       }
910	       break;
911            default:
912               _mesa_problem(ctx, "Bad format (GL_DECAL) in texture_apply");
913               return;
914	 }
915	 break;
916
917      case GL_BLEND:
918         UNCLAMPED_FLOAT_TO_CHAN(Rc, texUnit->EnvColor[0]);
919         UNCLAMPED_FLOAT_TO_CHAN(Gc, texUnit->EnvColor[1]);
920         UNCLAMPED_FLOAT_TO_CHAN(Bc, texUnit->EnvColor[2]);
921         UNCLAMPED_FLOAT_TO_CHAN(Ac, texUnit->EnvColor[3]);
922	 switch (format) {
923	    case GL_ALPHA:
924	       for (i=0;i<n;i++) {
925		  /* Cv = Cf */
926		  /* Av = AfAt */
927                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
928	       }
929	       break;
930            case GL_LUMINANCE:
931	       for (i=0;i<n;i++) {
932		  /* Cv = Cf(1-Lt) + CcLt */
933		  GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
934		  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
935		  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
936		  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
937		  /* Av = Af */
938	       }
939	       break;
940	    case GL_LUMINANCE_ALPHA:
941	       for (i=0;i<n;i++) {
942		  /* Cv = Cf(1-Lt) + CcLt */
943		  GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
944		  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
945		  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
946		  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
947		  /* Av = AfAt */
948		  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
949	       }
950	       break;
951            case GL_INTENSITY:
952	       for (i=0;i<n;i++) {
953		  /* Cv = Cf(1-It) + CcIt */
954		  GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
955		  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
956		  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
957		  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
958                  /* Av = Af(1-It) + Ac*It */
959                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
960               }
961               break;
962	    case GL_RGB:
963	       for (i=0;i<n;i++) {
964		  /* Cv = Cf(1-Ct) + CcCt */
965		  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
966		  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
967		  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
968		  /* Av = Af */
969	       }
970	       break;
971	    case GL_RGBA:
972	       for (i=0;i<n;i++) {
973		  /* Cv = Cf(1-Ct) + CcCt */
974		  rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
975		  rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
976		  rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
977		  /* Av = AfAt */
978		  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
979	       }
980	       break;
981            default:
982               _mesa_problem(ctx, "Bad format (GL_BLEND) in texture_apply");
983               return;
984	 }
985	 break;
986
987     /* XXX don't clamp results if GLchan is float??? */
988
989      case GL_ADD:  /* GL_EXT_texture_add_env */
990         switch (format) {
991            case GL_ALPHA:
992               for (i=0;i<n;i++) {
993                  /* Rv = Rf */
994                  /* Gv = Gf */
995                  /* Bv = Bf */
996                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
997               }
998               break;
999            case GL_LUMINANCE:
1000               for (i=0;i<n;i++) {
1001                  ChanTemp Lt = texel[i][RCOMP];
1002                  ChanTemp r = rgba[i][RCOMP] + Lt;
1003                  ChanTemp g = rgba[i][GCOMP] + Lt;
1004                  ChanTemp b = rgba[i][BCOMP] + Lt;
1005                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1006                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1007                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1008                  /* Av = Af */
1009               }
1010               break;
1011            case GL_LUMINANCE_ALPHA:
1012               for (i=0;i<n;i++) {
1013                  ChanTemp Lt = texel[i][RCOMP];
1014                  ChanTemp r = rgba[i][RCOMP] + Lt;
1015                  ChanTemp g = rgba[i][GCOMP] + Lt;
1016                  ChanTemp b = rgba[i][BCOMP] + Lt;
1017                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1018                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1019                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1020                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
1021               }
1022               break;
1023            case GL_INTENSITY:
1024               for (i=0;i<n;i++) {
1025                  GLchan It = texel[i][RCOMP];
1026                  ChanTemp r = rgba[i][RCOMP] + It;
1027                  ChanTemp g = rgba[i][GCOMP] + It;
1028                  ChanTemp b = rgba[i][BCOMP] + It;
1029                  ChanTemp a = rgba[i][ACOMP] + It;
1030                  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1031                  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1032                  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1033                  rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
1034               }
1035               break;
1036	    case GL_RGB:
1037	       for (i=0;i<n;i++) {
1038                  ChanTemp r = rgba[i][RCOMP] + texel[i][RCOMP];
1039                  ChanTemp g = rgba[i][GCOMP] + texel[i][GCOMP];
1040                  ChanTemp b = rgba[i][BCOMP] + texel[i][BCOMP];
1041		  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1042		  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1043		  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1044		  /* Av = Af */
1045	       }
1046	       break;
1047	    case GL_RGBA:
1048	       for (i=0;i<n;i++) {
1049                  ChanTemp r = rgba[i][RCOMP] + texel[i][RCOMP];
1050                  ChanTemp g = rgba[i][GCOMP] + texel[i][GCOMP];
1051                  ChanTemp b = rgba[i][BCOMP] + texel[i][BCOMP];
1052		  rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1053		  rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1054		  rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1055                  rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
1056               }
1057               break;
1058            default:
1059               _mesa_problem(ctx, "Bad format (GL_ADD) in texture_apply");
1060               return;
1061	 }
1062	 break;
1063
1064      default:
1065         _mesa_problem(ctx, "Bad env mode in texture_apply");
1066         return;
1067   }
1068}
1069
1070
1071
1072/**
1073 * Apply texture mapping to a span of fragments.
1074 */
1075void
1076_swrast_texture_span( GLcontext *ctx, SWspan *span )
1077{
1078   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1079   GLchan primary_rgba[MAX_WIDTH][4];
1080   GLuint unit;
1081
1082   ASSERT(span->end < MAX_WIDTH);
1083   ASSERT(span->arrayMask & SPAN_TEXTURE);
1084
1085   /*
1086    * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
1087    */
1088   if (swrast->_AnyTextureCombine)
1089      MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan));
1090
1091   /*
1092    * Must do all texture sampling before combining in order to
1093    * accomodate GL_ARB_texture_env_crossbar.
1094    */
1095   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1096      if (ctx->Texture.Unit[unit]._ReallyEnabled) {
1097         const GLfloat (*texcoords)[4]
1098            = (const GLfloat (*)[4])
1099            span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
1100         const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1101         const struct gl_texture_object *curObj = texUnit->_Current;
1102         GLfloat *lambda = span->array->lambda[unit];
1103         GLchan (*texels)[4] = (GLchan (*)[4])
1104            (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan)));
1105
1106         /* adjust texture lod (lambda) */
1107         if (span->arrayMask & SPAN_LAMBDA) {
1108            if (texUnit->LodBias + curObj->LodBias != 0.0F) {
1109               /* apply LOD bias, but don't clamp yet */
1110               const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
1111                                          -ctx->Const.MaxTextureLodBias,
1112                                          ctx->Const.MaxTextureLodBias);
1113               GLuint i;
1114               for (i = 0; i < span->end; i++) {
1115                  lambda[i] += bias;
1116               }
1117            }
1118
1119            if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
1120               /* apply LOD clamping to lambda */
1121               const GLfloat min = curObj->MinLod;
1122               const GLfloat max = curObj->MaxLod;
1123               GLuint i;
1124               for (i = 0; i < span->end; i++) {
1125                  GLfloat l = lambda[i];
1126                  lambda[i] = CLAMP(l, min, max);
1127               }
1128            }
1129         }
1130
1131         /* Sample the texture (span->end = number of fragments) */
1132         swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
1133                                      texcoords, lambda, texels );
1134
1135         /* GL_SGI_texture_color_table */
1136         if (texUnit->ColorTableEnabled) {
1137#if CHAN_TYPE == GL_UNSIGNED_BYTE
1138            _mesa_lookup_rgba_ubyte(&texUnit->ColorTable, span->end, texels);
1139#elif CHAN_TYPE == GL_UNSIGNED_SHORT
1140            _mesa_lookup_rgba_ubyte(&texUnit->ColorTable, span->end, texels);
1141#else
1142            _mesa_lookup_rgba_float(&texUnit->ColorTable, span->end, texels);
1143#endif
1144         }
1145      }
1146   }
1147
1148   /*
1149    * OK, now apply the texture (aka texture combine/blend).
1150    * We modify the span->color.rgba values.
1151    */
1152   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1153      if (ctx->Texture.Unit[unit]._ReallyEnabled) {
1154         const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1155         if (texUnit->_CurrentCombine != &texUnit->_EnvMode ) {
1156            texture_combine( ctx, unit, span->end,
1157                             (CONST GLchan (*)[4]) primary_rgba,
1158                             swrast->TexelBuffer,
1159                             span->array->rgba );
1160         }
1161         else {
1162            /* conventional texture blend */
1163            const GLchan (*texels)[4] = (const GLchan (*)[4])
1164               (swrast->TexelBuffer + unit *
1165                (span->end * 4 * sizeof(GLchan)));
1166            texture_apply( ctx, texUnit, span->end,
1167                           (CONST GLchan (*)[4]) primary_rgba, texels,
1168                           span->array->rgba );
1169         }
1170      }
1171   }
1172}
1173