Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / swrast / s_texcombine.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 #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  */
42 typedef float (*float4_array)[4];
43
44
45 /**
46  * Return array of texels for given unit.
47  */
48 static INLINE float4_array
49 get_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  */
74 static void
75 texture_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
541 end:
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  */
553 static void
554 swizzle_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  */
582 void
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->Sampler.LodBias != 0.0F) {
635                /* apply LOD bias, but don't clamp yet */
636                const GLfloat bias = CLAMP(texUnit->LodBias + curObj->Sampler.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->Sampler.MinLod != -1000.0 ||
646                 curObj->Sampler.MaxLod != 1000.0) {
647                /* apply LOD clamping to lambda */
648                const GLfloat min = curObj->Sampler.MinLod;
649                const GLfloat max = curObj->Sampler.MaxLod;
650                GLuint i;
651                for (i = 0; i < span->end; i++) {
652                   GLfloat l = lambda[i];
653                   lambda[i] = CLAMP(l, min, max);
654                }
655             }
656          }
657
658          /* Sample the texture (span->end = number of fragments) */
659          swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
660                                       texcoords, lambda, texels );
661
662          /* manipulate the span values of the bump target
663             not sure this can work correctly even ignoring
664             the problem that channel is unsigned */
665          for (i = 0; i < span->end; i++) {
666             targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
667                                   rotMatrix01) / targetcoords[i][3];
668             targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
669                                   rotMatrix11) / targetcoords[i][3];
670          }
671       }
672    }
673
674    /*
675     * Must do all texture sampling before combining in order to
676     * accomodate GL_ARB_texture_env_crossbar.
677     */
678    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
679       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
680       if (texUnit->_ReallyEnabled &&
681           texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
682          const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
683             span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
684          const struct gl_texture_object *curObj = texUnit->_Current;
685          GLfloat *lambda = span->array->lambda[unit];
686          float4_array texels = get_texel_array(swrast, unit);
687
688          /* adjust texture lod (lambda) */
689          if (span->arrayMask & SPAN_LAMBDA) {
690             if (texUnit->LodBias + curObj->Sampler.LodBias != 0.0F) {
691                /* apply LOD bias, but don't clamp yet */
692                const GLfloat bias = CLAMP(texUnit->LodBias + curObj->Sampler.LodBias,
693                                           -ctx->Const.MaxTextureLodBias,
694                                           ctx->Const.MaxTextureLodBias);
695                GLuint i;
696                for (i = 0; i < span->end; i++) {
697                   lambda[i] += bias;
698                }
699             }
700
701             if (curObj->Sampler.MinLod != -1000.0 ||
702                 curObj->Sampler.MaxLod != 1000.0) {
703                /* apply LOD clamping to lambda */
704                const GLfloat min = curObj->Sampler.MinLod;
705                const GLfloat max = curObj->Sampler.MaxLod;
706                GLuint i;
707                for (i = 0; i < span->end; i++) {
708                   GLfloat l = lambda[i];
709                   lambda[i] = CLAMP(l, min, max);
710                }
711             }
712          }
713          else if (curObj->Sampler.MaxAnisotropy > 1.0 &&
714                   curObj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
715             /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
716              * it requires the current SWspan *span as an additional parameter.
717              * In order to keep the same function signature, the unused lambda
718              * parameter will be modified to actually contain the SWspan pointer.
719              * This is a Hack. To make it right, the texture_sample_func
720              * signature and all implementing functions need to be modified.
721              */
722             /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
723             lambda = (GLfloat *)span;
724          }
725
726          /* Sample the texture (span->end = number of fragments) */
727          swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
728                                       texcoords, lambda, texels );
729
730          /* GL_EXT_texture_swizzle */
731          if (curObj->_Swizzle != SWIZZLE_NOOP) {
732             swizzle_texels(curObj->_Swizzle, span->end, texels);
733          }
734       }
735    }
736
737    /*
738     * OK, now apply the texture (aka texture combine/blend).
739     * We modify the span->color.rgba values.
740     */
741    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
742       if (ctx->Texture.Unit[unit]._ReallyEnabled) {
743          texture_combine( ctx, unit, span->end,
744                           primary_rgba,
745                           swrast->TexelBuffer,
746                           span->array->rgba );
747       }
748    }
749
750    free(primary_rgba);
751 }