Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 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->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_SGI_texture_color_table */
717
         if (texUnit->ColorTableEnabled) {
718
            _mesa_lookup_rgba_float(&texUnit->ColorTable, span->end, texels);
719
         }
720
 
721
         /* GL_EXT_texture_swizzle */
722
         if (curObj->_Swizzle != SWIZZLE_NOOP) {
723
            swizzle_texels(curObj->_Swizzle, span->end, texels);
724
         }
725
      }
726
   }
727
 
728
   /*
729
    * OK, now apply the texture (aka texture combine/blend).
730
    * We modify the span->color.rgba values.
731
    */
732
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
733
      if (ctx->Texture.Unit[unit]._ReallyEnabled) {
734
         texture_combine( ctx, unit, span->end,
735
                          primary_rgba,
736
                          swrast->TexelBuffer,
737
                          span->array->rgba );
738
      }
739
   }
740
 
741
   free(primary_rgba);
742
}