s_texcombine.c revision 9d20849516fe34bb0a430b007cef7878858cf0c7
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#include "main/glheader.h"
28#include "main/context.h"
29#include "main/colormac.h"
30#include "main/imports.h"
31#include "main/pixeltransfer.h"
32#include "program/prog_instruction.h"
33
34#include "s_context.h"
35#include "s_texcombine.h"
36
37
38/**
39 * Pointer to array of float[4]
40 * This type makes the code below more concise and avoids a lot of casting.
41 */
42typedef float (*float4_array)[4];
43
44
45/**
46 * Return array of texels for given unit.
47 */
48static INLINE float4_array
49get_texel_array(SWcontext *swrast, GLuint unit)
50{
51   return (float4_array) (swrast->TexelBuffer + unit * MAX_WIDTH * 4);
52}
53
54
55
56/**
57 * Do texture application for:
58 *  GL_EXT_texture_env_combine
59 *  GL_ARB_texture_env_combine
60 *  GL_EXT_texture_env_dot3
61 *  GL_ARB_texture_env_dot3
62 *  GL_ATI_texture_env_combine3
63 *  GL_NV_texture_env_combine4
64 *  conventional GL texture env modes
65 *
66 * \param ctx          rendering context
67 * \param unit         the texture combiner unit
68 * \param n            number of fragments to process (span width)
69 * \param primary_rgba incoming fragment color array
70 * \param texelBuffer  pointer to texel colors for all texture units
71 *
72 * \param rgba         incoming/result fragment colors
73 */
74static void
75texture_combine( struct gl_context *ctx, GLuint unit, GLuint n,
76                 const float4_array primary_rgba,
77                 const GLfloat *texelBuffer,
78                 GLchan (*rgbaChan)[4] )
79{
80   SWcontext *swrast = SWRAST_CONTEXT(ctx);
81   const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
82   const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
83   float4_array argRGB[MAX_COMBINER_TERMS];
84   float4_array argA[MAX_COMBINER_TERMS];
85   const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
86   const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
87   const GLuint numArgsRGB = combine->_NumArgsRGB;
88   const GLuint numArgsA = combine->_NumArgsA;
89   float4_array ccolor[4], rgba;
90   GLuint i, term;
91
92   /* alloc temp pixel buffers */
93   rgba = (float4_array) malloc(4 * n * sizeof(GLfloat));
94   if (!rgba) {
95      _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
96      return;
97   }
98
99   for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
100      ccolor[i] = (float4_array) malloc(4 * n * sizeof(GLfloat));
101      if (!ccolor[i]) {
102         while (i) {
103            free(ccolor[i]);
104            i--;
105         }
106         _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
107         return;
108      }
109   }
110
111   for (i = 0; i < n; i++) {
112      rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
113      rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
114      rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
115      rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
116   }
117
118   /*
119   printf("modeRGB 0x%x  modeA 0x%x  srcRGB1 0x%x  srcA1 0x%x  srcRGB2 0x%x  srcA2 0x%x\n",
120          combine->ModeRGB,
121          combine->ModeA,
122          combine->SourceRGB[0],
123          combine->SourceA[0],
124          combine->SourceRGB[1],
125          combine->SourceA[1]);
126   */
127
128   /*
129    * Do operand setup for up to 4 operands.  Loop over the terms.
130    */
131   for (term = 0; term < numArgsRGB; term++) {
132      const GLenum srcRGB = combine->SourceRGB[term];
133      const GLenum operandRGB = combine->OperandRGB[term];
134
135      switch (srcRGB) {
136         case GL_TEXTURE:
137            argRGB[term] = get_texel_array(swrast, unit);
138            break;
139         case GL_PRIMARY_COLOR:
140            argRGB[term] = primary_rgba;
141            break;
142         case GL_PREVIOUS:
143            argRGB[term] = rgba;
144            break;
145         case GL_CONSTANT:
146            {
147               float4_array c = ccolor[term];
148               GLfloat red   = textureUnit->EnvColor[0];
149               GLfloat green = textureUnit->EnvColor[1];
150               GLfloat blue  = textureUnit->EnvColor[2];
151               GLfloat alpha = textureUnit->EnvColor[3];
152               for (i = 0; i < n; i++) {
153                  ASSIGN_4V(c[i], red, green, blue, alpha);
154               }
155               argRGB[term] = ccolor[term];
156            }
157            break;
158	 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
159	  */
160	 case GL_ZERO:
161            {
162               float4_array c = ccolor[term];
163               for (i = 0; i < n; i++) {
164                  ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
165               }
166               argRGB[term] = ccolor[term];
167            }
168            break;
169	 case GL_ONE:
170            {
171               float4_array c = ccolor[term];
172               for (i = 0; i < n; i++) {
173                  ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
174               }
175               argRGB[term] = ccolor[term];
176            }
177            break;
178         default:
179            /* ARB_texture_env_crossbar source */
180            {
181               const GLuint srcUnit = srcRGB - GL_TEXTURE0;
182               ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
183               if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
184                  goto end;
185               argRGB[term] = get_texel_array(swrast, srcUnit);
186            }
187      }
188
189      if (operandRGB != GL_SRC_COLOR) {
190         float4_array src = argRGB[term];
191         float4_array dst = ccolor[term];
192
193         /* point to new arg[term] storage */
194         argRGB[term] = ccolor[term];
195
196         switch (operandRGB) {
197         case GL_ONE_MINUS_SRC_COLOR:
198            for (i = 0; i < n; i++) {
199               dst[i][RCOMP] = 1.0F - src[i][RCOMP];
200               dst[i][GCOMP] = 1.0F - src[i][GCOMP];
201               dst[i][BCOMP] = 1.0F - src[i][BCOMP];
202            }
203            break;
204         case GL_SRC_ALPHA:
205            for (i = 0; i < n; i++) {
206               dst[i][RCOMP] =
207               dst[i][GCOMP] =
208               dst[i][BCOMP] = src[i][ACOMP];
209            }
210            break;
211         case GL_ONE_MINUS_SRC_ALPHA:
212            for (i = 0; i < n; i++) {
213               dst[i][RCOMP] =
214               dst[i][GCOMP] =
215               dst[i][BCOMP] = 1.0F - src[i][ACOMP];
216            }
217            break;
218         default:
219            _mesa_problem(ctx, "Bad operandRGB");
220         }
221      }
222   }
223
224   /*
225    * Set up the argA[term] pointers
226    */
227   for (term = 0; term < numArgsA; term++) {
228      const GLenum srcA = combine->SourceA[term];
229      const GLenum operandA = combine->OperandA[term];
230
231      switch (srcA) {
232         case GL_TEXTURE:
233            argA[term] = get_texel_array(swrast, unit);
234            break;
235         case GL_PRIMARY_COLOR:
236            argA[term] = primary_rgba;
237            break;
238         case GL_PREVIOUS:
239            argA[term] = rgba;
240            break;
241         case GL_CONSTANT:
242            {
243               float4_array c = ccolor[term];
244               GLfloat alpha = textureUnit->EnvColor[3];
245               for (i = 0; i < n; i++)
246                  c[i][ACOMP] = alpha;
247               argA[term] = ccolor[term];
248            }
249            break;
250	 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
251	  */
252	 case GL_ZERO:
253            {
254               float4_array c = ccolor[term];
255               for (i = 0; i < n; i++)
256                  c[i][ACOMP] = 0.0F;
257               argA[term] = ccolor[term];
258            }
259            break;
260	 case GL_ONE:
261            {
262               float4_array c = ccolor[term];
263               for (i = 0; i < n; i++)
264                  c[i][ACOMP] = 1.0F;
265               argA[term] = ccolor[term];
266            }
267            break;
268         default:
269            /* ARB_texture_env_crossbar source */
270            {
271               const GLuint srcUnit = srcA - GL_TEXTURE0;
272               ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
273               if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
274                  goto end;
275               argA[term] = get_texel_array(swrast, srcUnit);
276            }
277      }
278
279      if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
280         float4_array src = argA[term];
281         float4_array dst = ccolor[term];
282         argA[term] = ccolor[term];
283         for (i = 0; i < n; i++) {
284            dst[i][ACOMP] = 1.0F - src[i][ACOMP];
285         }
286      }
287   }
288
289   /* RGB channel combine */
290   {
291      float4_array arg0 = argRGB[0];
292      float4_array arg1 = argRGB[1];
293      float4_array arg2 = argRGB[2];
294      float4_array arg3 = argRGB[3];
295
296      switch (combine->ModeRGB) {
297      case GL_REPLACE:
298         for (i = 0; i < n; i++) {
299            rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
300            rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
301            rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
302         }
303         break;
304      case GL_MODULATE:
305         for (i = 0; i < n; i++) {
306            rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
307            rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
308            rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
309         }
310         break;
311      case GL_ADD:
312         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
313            /* (a * b) + (c * d) */
314            for (i = 0; i < n; i++) {
315               rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
316                                 arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
317               rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
318                                 arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
319               rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
320                                 arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
321            }
322         }
323         else {
324            /* 2-term addition */
325            for (i = 0; i < n; i++) {
326               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
327               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
328               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
329            }
330         }
331         break;
332      case GL_ADD_SIGNED:
333         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
334            /* (a * b) + (c * d) - 0.5 */
335            for (i = 0; i < n; i++) {
336               rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
337                                 arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5F) * scaleRGB;
338               rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
339                                 arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5F) * scaleRGB;
340               rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
341                                 arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5F) * scaleRGB;
342            }
343         }
344         else {
345            for (i = 0; i < n; i++) {
346               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5F) * scaleRGB;
347               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5F) * scaleRGB;
348               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5F) * scaleRGB;
349            }
350         }
351         break;
352      case GL_INTERPOLATE:
353         for (i = 0; i < n; i++) {
354            rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
355                          arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
356            rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
357                          arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
358            rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
359                          arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
360         }
361         break;
362      case GL_SUBTRACT:
363         for (i = 0; i < n; i++) {
364            rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
365            rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
366            rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
367         }
368         break;
369      case GL_DOT3_RGB_EXT:
370      case GL_DOT3_RGBA_EXT:
371         /* Do not scale the result by 1 2 or 4 */
372         for (i = 0; i < n; i++) {
373            GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
374                           (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
375                           (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
376               * 4.0F;
377            dot = CLAMP(dot, 0.0F, 1.0F);
378            rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
379         }
380         break;
381      case GL_DOT3_RGB:
382      case GL_DOT3_RGBA:
383         /* DO scale the result by 1 2 or 4 */
384         for (i = 0; i < n; i++) {
385            GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
386                           (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
387                           (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
388               * 4.0F * scaleRGB;
389            dot = CLAMP(dot, 0.0F, 1.0F);
390            rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
391         }
392         break;
393      case GL_MODULATE_ADD_ATI:
394         for (i = 0; i < n; i++) {
395            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
396                              arg1[i][RCOMP]) * scaleRGB;
397            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
398                              arg1[i][GCOMP]) * scaleRGB;
399            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
400                              arg1[i][BCOMP]) * scaleRGB;
401	 }
402         break;
403      case GL_MODULATE_SIGNED_ADD_ATI:
404         for (i = 0; i < n; i++) {
405            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
406                              arg1[i][RCOMP] - 0.5F) * scaleRGB;
407            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
408                              arg1[i][GCOMP] - 0.5F) * scaleRGB;
409            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
410                              arg1[i][BCOMP] - 0.5F) * scaleRGB;
411	 }
412         break;
413      case GL_MODULATE_SUBTRACT_ATI:
414         for (i = 0; i < n; i++) {
415            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
416                              arg1[i][RCOMP]) * scaleRGB;
417            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
418                              arg1[i][GCOMP]) * scaleRGB;
419            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
420                              arg1[i][BCOMP]) * scaleRGB;
421	 }
422         break;
423      case GL_BUMP_ENVMAP_ATI:
424         /* this produces a fixed rgba color, and the coord calc is done elsewhere */
425         for (i = 0; i < n; i++) {
426            /* rgba result is 0,0,0,1 */
427            rgba[i][RCOMP] = 0.0;
428            rgba[i][GCOMP] = 0.0;
429            rgba[i][BCOMP] = 0.0;
430            rgba[i][ACOMP] = 1.0;
431	 }
432         goto end; /* no alpha processing */
433      default:
434         _mesa_problem(ctx, "invalid combine mode");
435      }
436   }
437
438   /* Alpha channel combine */
439   {
440      float4_array arg0 = argA[0];
441      float4_array arg1 = argA[1];
442      float4_array arg2 = argA[2];
443      float4_array arg3 = argA[3];
444
445      switch (combine->ModeA) {
446      case GL_REPLACE:
447         for (i = 0; i < n; i++) {
448            rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
449         }
450         break;
451      case GL_MODULATE:
452         for (i = 0; i < n; i++) {
453            rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
454         }
455         break;
456      case GL_ADD:
457         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
458            /* (a * b) + (c * d) */
459            for (i = 0; i < n; i++) {
460               rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
461                                 arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
462            }
463         }
464         else {
465            /* two-term add */
466            for (i = 0; i < n; i++) {
467               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
468            }
469         }
470         break;
471      case GL_ADD_SIGNED:
472         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
473            /* (a * b) + (c * d) - 0.5 */
474            for (i = 0; i < n; i++) {
475               rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
476                                 arg2[i][ACOMP] * arg3[i][ACOMP] -
477                                 0.5F) * scaleA;
478            }
479         }
480         else {
481            /* a + b - 0.5 */
482            for (i = 0; i < n; i++) {
483               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
484            }
485         }
486         break;
487      case GL_INTERPOLATE:
488         for (i = 0; i < n; i++) {
489            rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
490                              arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
491               * scaleA;
492         }
493         break;
494      case GL_SUBTRACT:
495         for (i = 0; i < n; i++) {
496            rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
497         }
498         break;
499      case GL_MODULATE_ADD_ATI:
500         for (i = 0; i < n; i++) {
501            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
502                              + arg1[i][ACOMP]) * scaleA;
503         }
504         break;
505      case GL_MODULATE_SIGNED_ADD_ATI:
506         for (i = 0; i < n; i++) {
507            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
508                              arg1[i][ACOMP] - 0.5F) * scaleA;
509         }
510         break;
511      case GL_MODULATE_SUBTRACT_ATI:
512         for (i = 0; i < n; i++) {
513            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
514                              - arg1[i][ACOMP]) * scaleA;
515         }
516         break;
517      default:
518         _mesa_problem(ctx, "invalid combine mode");
519      }
520   }
521
522   /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
523    * This is kind of a kludge.  It would have been better if the spec
524    * were written such that the GL_COMBINE_ALPHA value could be set to
525    * GL_DOT3.
526    */
527   if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
528       combine->ModeRGB == GL_DOT3_RGBA) {
529      for (i = 0; i < n; i++) {
530	 rgba[i][ACOMP] = rgba[i][RCOMP];
531      }
532   }
533
534   for (i = 0; i < n; i++) {
535      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
536      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
537      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
538      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
539   }
540
541end:
542   for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
543      free(ccolor[i]);
544   }
545   free(rgba);
546}
547
548
549/**
550 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
551 * See GL_EXT_texture_swizzle.
552 */
553static void
554swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
555{
556   const GLuint swzR = GET_SWZ(swizzle, 0);
557   const GLuint swzG = GET_SWZ(swizzle, 1);
558   const GLuint swzB = GET_SWZ(swizzle, 2);
559   const GLuint swzA = GET_SWZ(swizzle, 3);
560   GLfloat vector[6];
561   GLuint i;
562
563   vector[SWIZZLE_ZERO] = 0;
564   vector[SWIZZLE_ONE] = 1.0F;
565
566   for (i = 0; i < count; i++) {
567      vector[SWIZZLE_X] = texels[i][0];
568      vector[SWIZZLE_Y] = texels[i][1];
569      vector[SWIZZLE_Z] = texels[i][2];
570      vector[SWIZZLE_W] = texels[i][3];
571      texels[i][RCOMP] = vector[swzR];
572      texels[i][GCOMP] = vector[swzG];
573      texels[i][BCOMP] = vector[swzB];
574      texels[i][ACOMP] = vector[swzA];
575   }
576}
577
578
579/**
580 * Apply texture mapping to a span of fragments.
581 */
582void
583_swrast_texture_span( struct gl_context *ctx, SWspan *span )
584{
585   SWcontext *swrast = SWRAST_CONTEXT(ctx);
586   float4_array primary_rgba;
587   GLuint unit;
588
589   primary_rgba = (float4_array) malloc(span->end * 4 * sizeof(GLfloat));
590
591   if (!primary_rgba) {
592      _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
593      return;
594   }
595
596   ASSERT(span->end <= MAX_WIDTH);
597
598   /*
599    * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
600    */
601   if (swrast->_TextureCombinePrimary) {
602      GLuint i;
603      for (i = 0; i < span->end; i++) {
604         primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
605         primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
606         primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
607         primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
608      }
609   }
610
611   /* First must sample all bump maps */
612   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
613      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
614
615      if (texUnit->_ReallyEnabled &&
616         texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
617         const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
618            span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
619         float4_array targetcoords =
620            span->array->attribs[FRAG_ATTRIB_TEX0 +
621               ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
622
623         const struct gl_texture_object *curObj = texUnit->_Current;
624         GLfloat *lambda = span->array->lambda[unit];
625         float4_array texels = get_texel_array(swrast, unit);
626         GLuint i;
627         GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
628         GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
629         GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
630         GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];
631
632         /* adjust texture lod (lambda) */
633         if (span->arrayMask & SPAN_LAMBDA) {
634            if (texUnit->LodBias + curObj->LodBias != 0.0F) {
635               /* apply LOD bias, but don't clamp yet */
636               const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
637                                          -ctx->Const.MaxTextureLodBias,
638                                          ctx->Const.MaxTextureLodBias);
639               GLuint i;
640               for (i = 0; i < span->end; i++) {
641                  lambda[i] += bias;
642               }
643            }
644
645            if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
646               /* apply LOD clamping to lambda */
647               const GLfloat min = curObj->MinLod;
648               const GLfloat max = curObj->MaxLod;
649               GLuint i;
650               for (i = 0; i < span->end; i++) {
651                  GLfloat l = lambda[i];
652                  lambda[i] = CLAMP(l, min, max);
653               }
654            }
655         }
656
657         /* Sample the texture (span->end = number of fragments) */
658         swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
659                                      texcoords, lambda, texels );
660
661         /* manipulate the span values of the bump target
662            not sure this can work correctly even ignoring
663            the problem that channel is unsigned */
664         for (i = 0; i < span->end; i++) {
665            targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
666                                  rotMatrix01) / targetcoords[i][3];
667            targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
668                                  rotMatrix11) / targetcoords[i][3];
669         }
670      }
671   }
672
673   /*
674    * Must do all texture sampling before combining in order to
675    * accomodate GL_ARB_texture_env_crossbar.
676    */
677   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
678      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
679      if (texUnit->_ReallyEnabled &&
680          texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
681         const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
682            span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
683         const struct gl_texture_object *curObj = texUnit->_Current;
684         GLfloat *lambda = span->array->lambda[unit];
685         float4_array texels = get_texel_array(swrast, unit);
686
687         /* adjust texture lod (lambda) */
688         if (span->arrayMask & SPAN_LAMBDA) {
689            if (texUnit->LodBias + curObj->LodBias != 0.0F) {
690               /* apply LOD bias, but don't clamp yet */
691               const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
692                                          -ctx->Const.MaxTextureLodBias,
693                                          ctx->Const.MaxTextureLodBias);
694               GLuint i;
695               for (i = 0; i < span->end; i++) {
696                  lambda[i] += bias;
697               }
698            }
699
700            if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
701               /* apply LOD clamping to lambda */
702               const GLfloat min = curObj->MinLod;
703               const GLfloat max = curObj->MaxLod;
704               GLuint i;
705               for (i = 0; i < span->end; i++) {
706                  GLfloat l = lambda[i];
707                  lambda[i] = CLAMP(l, min, max);
708               }
709            }
710         }
711
712         /* Sample the texture (span->end = number of fragments) */
713         swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
714                                      texcoords, lambda, texels );
715
716         /* GL_EXT_texture_swizzle */
717         if (curObj->_Swizzle != SWIZZLE_NOOP) {
718            swizzle_texels(curObj->_Swizzle, span->end, texels);
719         }
720      }
721   }
722
723   /*
724    * OK, now apply the texture (aka texture combine/blend).
725    * We modify the span->color.rgba values.
726    */
727   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
728      if (ctx->Texture.Unit[unit]._ReallyEnabled) {
729         texture_combine( ctx, unit, span->end,
730                          primary_rgba,
731                          swrast->TexelBuffer,
732                          span->array->rgba );
733      }
734   }
735
736   free(primary_rgba);
737}
738