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