Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
5564 serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5
 * Copyright (C) 2009  VMware, Inc.   All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
 
26
 
27
#include "main/glheader.h"
28
#include "main/context.h"
29
#include "main/imports.h"
30
#include "main/macros.h"
31
#include "main/pixeltransfer.h"
32
#include "main/samplerobj.h"
33
#include "program/prog_instruction.h"
34
 
35
#include "s_context.h"
36
#include "s_texcombine.h"
37
 
38
 
39
/**
40
 * Pointer to array of float[4]
41
 * This type makes the code below more concise and avoids a lot of casting.
42
 */
43
typedef float (*float4_array)[4];
44
 
45
 
46
/**
47
 * Return array of texels for given unit.
48
 */
49
static inline float4_array
50
get_texel_array(SWcontext *swrast, GLuint unit)
51
{
52
#ifdef _OPENMP
53
   return (float4_array) (swrast->TexelBuffer + unit * SWRAST_MAX_WIDTH * 4 * omp_get_num_threads() + (SWRAST_MAX_WIDTH * 4 * omp_get_thread_num()));
54
#else
55
   return (float4_array) (swrast->TexelBuffer + unit * SWRAST_MAX_WIDTH * 4);
56
#endif
57
}
58
 
59
 
60
 
61
/**
62
 * Do texture application for:
63
 *  GL_EXT_texture_env_combine
64
 *  GL_ARB_texture_env_combine
65
 *  GL_EXT_texture_env_dot3
66
 *  GL_ARB_texture_env_dot3
67
 *  GL_ATI_texture_env_combine3
68
 *  GL_NV_texture_env_combine4
69
 *  conventional GL texture env modes
70
 *
71
 * \param ctx          rendering context
72
 * \param unit         the texture combiner unit
73
 * \param primary_rgba incoming fragment color array
74
 * \param texelBuffer  pointer to texel colors for all texture units
75
 *
76
 * \param span         two fields are used in this function:
77
 *                       span->end: number of fragments to process
78
 *                       span->array->rgba: incoming/result fragment colors
79
 */
80
static void
81
texture_combine( struct gl_context *ctx, GLuint unit,
82
                 const float4_array primary_rgba,
83
                 const GLfloat *texelBuffer,
84
                 SWspan *span )
85
{
86
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
87
   const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
88
   const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
89
   float4_array argRGB[MAX_COMBINER_TERMS];
90
   float4_array argA[MAX_COMBINER_TERMS];
91
   const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
92
   const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
93
   const GLuint numArgsRGB = combine->_NumArgsRGB;
94
   const GLuint numArgsA = combine->_NumArgsA;
95
   float4_array ccolor[4], rgba;
96
   GLuint i, term;
97
   GLuint n = span->end;
98
   GLchan (*rgbaChan)[4] = span->array->rgba;
99
 
100
   /* alloc temp pixel buffers */
101
   rgba = malloc(4 * n * sizeof(GLfloat));
102
   if (!rgba) {
103
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
104
      return;
105
   }
106
 
107
   for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
108
      ccolor[i] = malloc(4 * n * sizeof(GLfloat));
109
      if (!ccolor[i]) {
110
         while (i) {
111
            free(ccolor[i]);
112
            i--;
113
         }
114
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
115
         free(rgba);
116
         return;
117
      }
118
   }
119
 
120
   for (i = 0; i < n; i++) {
121
      rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
122
      rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
123
      rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
124
      rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
125
   }
126
 
127
   /*
128
   printf("modeRGB 0x%x  modeA 0x%x  srcRGB1 0x%x  srcA1 0x%x  srcRGB2 0x%x  srcA2 0x%x\n",
129
          combine->ModeRGB,
130
          combine->ModeA,
131
          combine->SourceRGB[0],
132
          combine->SourceA[0],
133
          combine->SourceRGB[1],
134
          combine->SourceA[1]);
135
   */
136
 
137
   /*
138
    * Do operand setup for up to 4 operands.  Loop over the terms.
139
    */
140
   for (term = 0; term < numArgsRGB; term++) {
141
      const GLenum srcRGB = combine->SourceRGB[term];
142
      const GLenum operandRGB = combine->OperandRGB[term];
143
 
144
      switch (srcRGB) {
145
         case GL_TEXTURE:
146
            argRGB[term] = get_texel_array(swrast, unit);
147
            break;
148
         case GL_PRIMARY_COLOR:
149
            argRGB[term] = primary_rgba;
150
            break;
151
         case GL_PREVIOUS:
152
            argRGB[term] = rgba;
153
            break;
154
         case GL_CONSTANT:
155
            {
156
               float4_array c = ccolor[term];
157
               GLfloat red   = textureUnit->EnvColor[0];
158
               GLfloat green = textureUnit->EnvColor[1];
159
               GLfloat blue  = textureUnit->EnvColor[2];
160
               GLfloat alpha = textureUnit->EnvColor[3];
161
               for (i = 0; i < n; i++) {
162
                  ASSIGN_4V(c[i], red, green, blue, alpha);
163
               }
164
               argRGB[term] = ccolor[term];
165
            }
166
            break;
167
	 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
168
	  */
169
	 case GL_ZERO:
170
            {
171
               float4_array c = ccolor[term];
172
               for (i = 0; i < n; i++) {
173
                  ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
174
               }
175
               argRGB[term] = ccolor[term];
176
            }
177
            break;
178
	 case GL_ONE:
179
            {
180
               float4_array c = ccolor[term];
181
               for (i = 0; i < n; i++) {
182
                  ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
183
               }
184
               argRGB[term] = ccolor[term];
185
            }
186
            break;
187
         default:
188
            /* ARB_texture_env_crossbar source */
189
            {
190
               const GLuint srcUnit = srcRGB - GL_TEXTURE0;
191
               assert(srcUnit < ctx->Const.MaxTextureUnits);
192
               if (!ctx->Texture.Unit[srcUnit]._Current)
193
                  goto end;
194
               argRGB[term] = get_texel_array(swrast, srcUnit);
195
            }
196
      }
197
 
198
      if (operandRGB != GL_SRC_COLOR) {
199
         float4_array src = argRGB[term];
200
         float4_array dst = ccolor[term];
201
 
202
         /* point to new arg[term] storage */
203
         argRGB[term] = ccolor[term];
204
 
205
         switch (operandRGB) {
206
         case GL_ONE_MINUS_SRC_COLOR:
207
            for (i = 0; i < n; i++) {
208
               dst[i][RCOMP] = 1.0F - src[i][RCOMP];
209
               dst[i][GCOMP] = 1.0F - src[i][GCOMP];
210
               dst[i][BCOMP] = 1.0F - src[i][BCOMP];
211
            }
212
            break;
213
         case GL_SRC_ALPHA:
214
            for (i = 0; i < n; i++) {
215
               dst[i][RCOMP] =
216
               dst[i][GCOMP] =
217
               dst[i][BCOMP] = src[i][ACOMP];
218
            }
219
            break;
220
         case GL_ONE_MINUS_SRC_ALPHA:
221
            for (i = 0; i < n; i++) {
222
               dst[i][RCOMP] =
223
               dst[i][GCOMP] =
224
               dst[i][BCOMP] = 1.0F - src[i][ACOMP];
225
            }
226
            break;
227
         default:
228
            _mesa_problem(ctx, "Bad operandRGB");
229
         }
230
      }
231
   }
232
 
233
   /*
234
    * Set up the argA[term] pointers
235
    */
236
   for (term = 0; term < numArgsA; term++) {
237
      const GLenum srcA = combine->SourceA[term];
238
      const GLenum operandA = combine->OperandA[term];
239
 
240
      switch (srcA) {
241
         case GL_TEXTURE:
242
            argA[term] = get_texel_array(swrast, unit);
243
            break;
244
         case GL_PRIMARY_COLOR:
245
            argA[term] = primary_rgba;
246
            break;
247
         case GL_PREVIOUS:
248
            argA[term] = rgba;
249
            break;
250
         case GL_CONSTANT:
251
            {
252
               float4_array c = ccolor[term];
253
               GLfloat alpha = textureUnit->EnvColor[3];
254
               for (i = 0; i < n; i++)
255
                  c[i][ACOMP] = alpha;
256
               argA[term] = ccolor[term];
257
            }
258
            break;
259
	 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
260
	  */
261
	 case GL_ZERO:
262
            {
263
               float4_array c = ccolor[term];
264
               for (i = 0; i < n; i++)
265
                  c[i][ACOMP] = 0.0F;
266
               argA[term] = ccolor[term];
267
            }
268
            break;
269
	 case GL_ONE:
270
            {
271
               float4_array c = ccolor[term];
272
               for (i = 0; i < n; i++)
273
                  c[i][ACOMP] = 1.0F;
274
               argA[term] = ccolor[term];
275
            }
276
            break;
277
         default:
278
            /* ARB_texture_env_crossbar source */
279
            {
280
               const GLuint srcUnit = srcA - GL_TEXTURE0;
281
               assert(srcUnit < ctx->Const.MaxTextureUnits);
282
               if (!ctx->Texture.Unit[srcUnit]._Current)
283
                  goto end;
284
               argA[term] = get_texel_array(swrast, srcUnit);
285
            }
286
      }
287
 
288
      if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
289
         float4_array src = argA[term];
290
         float4_array dst = ccolor[term];
291
         argA[term] = ccolor[term];
292
         for (i = 0; i < n; i++) {
293
            dst[i][ACOMP] = 1.0F - src[i][ACOMP];
294
         }
295
      }
296
   }
297
 
298
   /* RGB channel combine */
299
   {
300
      float4_array arg0 = argRGB[0];
301
      float4_array arg1 = argRGB[1];
302
      float4_array arg2 = argRGB[2];
303
      float4_array arg3 = argRGB[3];
304
 
305
      switch (combine->ModeRGB) {
306
      case GL_REPLACE:
307
         for (i = 0; i < n; i++) {
308
            rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
309
            rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
310
            rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
311
         }
312
         break;
313
      case GL_MODULATE:
314
         for (i = 0; i < n; i++) {
315
            rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
316
            rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
317
            rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
318
         }
319
         break;
320
      case GL_ADD:
321
         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
322
            /* (a * b) + (c * d) */
323
            for (i = 0; i < n; i++) {
324
               rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
325
                                 arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
326
               rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
327
                                 arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
328
               rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
329
                                 arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
330
            }
331
         }
332
         else {
333
            /* 2-term addition */
334
            for (i = 0; i < n; i++) {
335
               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
336
               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
337
               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
338
            }
339
         }
340
         break;
341
      case GL_ADD_SIGNED:
342
         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
343
            /* (a * b) + (c * d) - 0.5 */
344
            for (i = 0; i < n; i++) {
345
               rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
346
                                 arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5F) * scaleRGB;
347
               rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
348
                                 arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5F) * scaleRGB;
349
               rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
350
                                 arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5F) * scaleRGB;
351
            }
352
         }
353
         else {
354
            for (i = 0; i < n; i++) {
355
               rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5F) * scaleRGB;
356
               rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5F) * scaleRGB;
357
               rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5F) * scaleRGB;
358
            }
359
         }
360
         break;
361
      case GL_INTERPOLATE:
362
         for (i = 0; i < n; i++) {
363
            rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
364
                          arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
365
            rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
366
                          arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
367
            rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
368
                          arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
369
         }
370
         break;
371
      case GL_SUBTRACT:
372
         for (i = 0; i < n; i++) {
373
            rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
374
            rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
375
            rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
376
         }
377
         break;
378
      case GL_DOT3_RGB_EXT:
379
      case GL_DOT3_RGBA_EXT:
380
         /* Do not scale the result by 1 2 or 4 */
381
         for (i = 0; i < n; i++) {
382
            GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
383
                           (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
384
                           (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
385
               * 4.0F;
386
            dot = CLAMP(dot, 0.0F, 1.0F);
387
            rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
388
         }
389
         break;
390
      case GL_DOT3_RGB:
391
      case GL_DOT3_RGBA:
392
         /* DO scale the result by 1 2 or 4 */
393
         for (i = 0; i < n; i++) {
394
            GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
395
                           (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
396
                           (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
397
               * 4.0F * scaleRGB;
398
            dot = CLAMP(dot, 0.0F, 1.0F);
399
            rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
400
         }
401
         break;
402
      case GL_MODULATE_ADD_ATI:
403
         for (i = 0; i < n; i++) {
404
            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
405
                              arg1[i][RCOMP]) * scaleRGB;
406
            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
407
                              arg1[i][GCOMP]) * scaleRGB;
408
            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
409
                              arg1[i][BCOMP]) * scaleRGB;
410
	 }
411
         break;
412
      case GL_MODULATE_SIGNED_ADD_ATI:
413
         for (i = 0; i < n; i++) {
414
            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
415
                              arg1[i][RCOMP] - 0.5F) * scaleRGB;
416
            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
417
                              arg1[i][GCOMP] - 0.5F) * scaleRGB;
418
            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
419
                              arg1[i][BCOMP] - 0.5F) * scaleRGB;
420
	 }
421
         break;
422
      case GL_MODULATE_SUBTRACT_ATI:
423
         for (i = 0; i < n; i++) {
424
            rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
425
                              arg1[i][RCOMP]) * scaleRGB;
426
            rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
427
                              arg1[i][GCOMP]) * scaleRGB;
428
            rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
429
                              arg1[i][BCOMP]) * scaleRGB;
430
	 }
431
         break;
432
      default:
433
         _mesa_problem(ctx, "invalid combine mode");
434
      }
435
   }
436
 
437
   /* Alpha channel combine */
438
   {
439
      float4_array arg0 = argA[0];
440
      float4_array arg1 = argA[1];
441
      float4_array arg2 = argA[2];
442
      float4_array arg3 = argA[3];
443
 
444
      switch (combine->ModeA) {
445
      case GL_REPLACE:
446
         for (i = 0; i < n; i++) {
447
            rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
448
         }
449
         break;
450
      case GL_MODULATE:
451
         for (i = 0; i < n; i++) {
452
            rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
453
         }
454
         break;
455
      case GL_ADD:
456
         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
457
            /* (a * b) + (c * d) */
458
            for (i = 0; i < n; i++) {
459
               rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
460
                                 arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
461
            }
462
         }
463
         else {
464
            /* two-term add */
465
            for (i = 0; i < n; i++) {
466
               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
467
            }
468
         }
469
         break;
470
      case GL_ADD_SIGNED:
471
         if (textureUnit->EnvMode == GL_COMBINE4_NV) {
472
            /* (a * b) + (c * d) - 0.5 */
473
            for (i = 0; i < n; i++) {
474
               rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
475
                                 arg2[i][ACOMP] * arg3[i][ACOMP] -
476
                                 0.5F) * scaleA;
477
            }
478
         }
479
         else {
480
            /* a + b - 0.5 */
481
            for (i = 0; i < n; i++) {
482
               rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
483
            }
484
         }
485
         break;
486
      case GL_INTERPOLATE:
487
         for (i = 0; i < n; i++) {
488
            rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
489
                              arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
490
               * scaleA;
491
         }
492
         break;
493
      case GL_SUBTRACT:
494
         for (i = 0; i < n; i++) {
495
            rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
496
         }
497
         break;
498
      case GL_MODULATE_ADD_ATI:
499
         for (i = 0; i < n; i++) {
500
            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
501
                              + arg1[i][ACOMP]) * scaleA;
502
         }
503
         break;
504
      case GL_MODULATE_SIGNED_ADD_ATI:
505
         for (i = 0; i < n; i++) {
506
            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
507
                              arg1[i][ACOMP] - 0.5F) * scaleA;
508
         }
509
         break;
510
      case GL_MODULATE_SUBTRACT_ATI:
511
         for (i = 0; i < n; i++) {
512
            rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
513
                              - arg1[i][ACOMP]) * scaleA;
514
         }
515
         break;
516
      default:
517
         _mesa_problem(ctx, "invalid combine mode");
518
      }
519
   }
520
 
521
   /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
522
    * This is kind of a kludge.  It would have been better if the spec
523
    * were written such that the GL_COMBINE_ALPHA value could be set to
524
    * GL_DOT3.
525
    */
526
   if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
527
       combine->ModeRGB == GL_DOT3_RGBA) {
528
      for (i = 0; i < n; i++) {
529
	 rgba[i][ACOMP] = rgba[i][RCOMP];
530
      }
531
   }
532
 
533
   for (i = 0; i < n; i++) {
534
      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
535
      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
536
      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
537
      UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
538
   }
539
   /* The span->array->rgba values are of CHAN type so set
540
    * span->array->ChanType field accordingly.
541
    */
542
   span->array->ChanType = CHAN_TYPE;
543
 
544
end:
545
   for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
546
      free(ccolor[i]);
547
   }
548
   free(rgba);
549
}
550
 
551
 
552
/**
553
 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
554
 * See GL_EXT_texture_swizzle.
555
 */
556
static void
557
swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
558
{
559
   const GLuint swzR = GET_SWZ(swizzle, 0);
560
   const GLuint swzG = GET_SWZ(swizzle, 1);
561
   const GLuint swzB = GET_SWZ(swizzle, 2);
562
   const GLuint swzA = GET_SWZ(swizzle, 3);
563
   GLfloat vector[6];
564
   GLuint i;
565
 
566
   vector[SWIZZLE_ZERO] = 0;
567
   vector[SWIZZLE_ONE] = 1.0F;
568
 
569
   for (i = 0; i < count; i++) {
570
      vector[SWIZZLE_X] = texels[i][0];
571
      vector[SWIZZLE_Y] = texels[i][1];
572
      vector[SWIZZLE_Z] = texels[i][2];
573
      vector[SWIZZLE_W] = texels[i][3];
574
      texels[i][RCOMP] = vector[swzR];
575
      texels[i][GCOMP] = vector[swzG];
576
      texels[i][BCOMP] = vector[swzB];
577
      texels[i][ACOMP] = vector[swzA];
578
   }
579
}
580
 
581
 
582
/**
583
 * Apply texture mapping to a span of fragments.
584
 */
585
void
586
_swrast_texture_span( struct gl_context *ctx, SWspan *span )
587
{
588
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
589
   float4_array primary_rgba;
590
   GLuint unit;
591
 
592
   if (!swrast->TexelBuffer) {
593
#ifdef _OPENMP
594
      const GLint maxThreads = omp_get_max_threads();
595
 
596
      /* TexelBuffer memory allocation needs to be done in a critical section
597
       * as this code runs in a parallel loop.
598
       * When entering the section, first check if TexelBuffer has been
599
       * initialized already by another thread while this thread was waiting.
600
       */
601
      #pragma omp critical
602
      if (!swrast->TexelBuffer) {
603
#else
604
      const GLint maxThreads = 1;
605
#endif
606
 
607
      /* TexelBuffer is also global and normally shared by all SWspan
608
       * instances; when running with multiple threads, create one per
609
       * thread.
610
       */
611
      swrast->TexelBuffer =
612
	 malloc(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits * maxThreads *
613
			    SWRAST_MAX_WIDTH * 4 * sizeof(GLfloat));
614
#ifdef _OPENMP
615
      } /* critical section */
616
#endif
617
 
618
      if (!swrast->TexelBuffer) {
619
	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
620
	 return;
621
      }
622
   }
623
 
624
   primary_rgba = malloc(span->end * 4 * sizeof(GLfloat));
625
 
626
   if (!primary_rgba) {
627
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
628
      return;
629
   }
630
 
631
   assert(span->end <= SWRAST_MAX_WIDTH);
632
 
633
   /*
634
    * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
635
    */
636
   if (swrast->_TextureCombinePrimary) {
637
      GLuint i;
638
      for (i = 0; i < span->end; i++) {
639
         primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
640
         primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
641
         primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
642
         primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
643
      }
644
   }
645
 
646
   /*
647
    * Must do all texture sampling before combining in order to
648
    * accommodate GL_ARB_texture_env_crossbar.
649
    */
650
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
651
      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
652
      if (texUnit->_Current) {
653
         const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
654
            span->array->attribs[VARYING_SLOT_TEX0 + unit];
655
         const struct gl_texture_object *curObj = texUnit->_Current;
656
         const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
657
         GLfloat *lambda = span->array->lambda[unit];
658
         float4_array texels = get_texel_array(swrast, unit);
659
 
660
         /* adjust texture lod (lambda) */
661
         if (span->arrayMask & SPAN_LAMBDA) {
662
            if (texUnit->LodBias + samp->LodBias != 0.0F) {
663
               /* apply LOD bias, but don't clamp yet */
664
               const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias,
665
                                          -ctx->Const.MaxTextureLodBias,
666
                                          ctx->Const.MaxTextureLodBias);
667
               GLuint i;
668
               for (i = 0; i < span->end; i++) {
669
                  lambda[i] += bias;
670
               }
671
            }
672
 
673
            if (samp->MinLod != -1000.0 ||
674
                samp->MaxLod != 1000.0) {
675
               /* apply LOD clamping to lambda */
676
               const GLfloat min = samp->MinLod;
677
               const GLfloat max = samp->MaxLod;
678
               GLuint i;
679
               for (i = 0; i < span->end; i++) {
680
                  GLfloat l = lambda[i];
681
                  lambda[i] = CLAMP(l, min, max);
682
               }
683
            }
684
         }
685
         else if (samp->MaxAnisotropy > 1.0 &&
686
                  samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
687
            /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
688
             * it requires the current SWspan *span as an additional parameter.
689
             * In order to keep the same function signature, the unused lambda
690
             * parameter will be modified to actually contain the SWspan pointer.
691
             * This is a Hack. To make it right, the texture_sample_func
692
             * signature and all implementing functions need to be modified.
693
             */
694
            /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
695
            lambda = (GLfloat *)span;
696
         }
697
 
698
         /* Sample the texture (span->end = number of fragments) */
699
         swrast->TextureSample[unit]( ctx, samp,
700
                                      ctx->Texture.Unit[unit]._Current,
701
                                      span->end, texcoords, lambda, texels );
702
 
703
         /* GL_EXT_texture_swizzle */
704
         if (curObj->_Swizzle != SWIZZLE_NOOP) {
705
            swizzle_texels(curObj->_Swizzle, span->end, texels);
706
         }
707
      }
708
   }
709
 
710
   /*
711
    * OK, now apply the texture (aka texture combine/blend).
712
    * We modify the span->color.rgba values.
713
    */
714
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
715
      if (ctx->Texture.Unit[unit]._Current)
716
         texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span);
717
   }
718
 
719
   free(primary_rgba);
720
}