2bdd4efaa20512c1e2aba0d71624aec1915b02d9
[mesa.git] / src / mesa / swrast / s_texcombine.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2005 Brian Paul 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include "glheader.h"
27 #include "context.h"
28 #include "colormac.h"
29 #include "imports.h"
30 #include "macros.h"
31 #include "pixel.h"
32
33 #include "s_context.h"
34 #include "s_texcombine.h"
35
36
37 #define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) )
38 #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
39
40
41 /**
42 * Do texture application for GL_ARB/EXT_texture_env_combine.
43 * This function also supports GL_{EXT,ARB}_texture_env_dot3 and
44 * GL_ATI_texture_env_combine3. Since "classic" texture environments are
45 * implemented using GL_ARB_texture_env_combine-like state, this same function
46 * is used for classic texture environment application as well.
47 *
48 * \param ctx rendering context
49 * \param textureUnit the texture unit to apply
50 * \param n number of fragments to process (span width)
51 * \param primary_rgba incoming fragment color array
52 * \param texelBuffer pointer to texel colors for all texture units
53 *
54 * \param rgba incoming colors, which get modified here
55 */
56 static void
57 texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
58 CONST GLchan (*primary_rgba)[4],
59 CONST GLchan *texelBuffer,
60 GLchan (*rgba)[4] )
61 {
62 const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
63 const GLchan (*argRGB [3])[4];
64 const GLchan (*argA [3])[4];
65 const GLuint RGBshift = textureUnit->_CurrentCombine->ScaleShiftRGB;
66 const GLuint Ashift = textureUnit->_CurrentCombine->ScaleShiftA;
67 #if CHAN_TYPE == GL_FLOAT
68 const GLchan RGBmult = (GLfloat) (1 << RGBshift);
69 const GLchan Amult = (GLfloat) (1 << Ashift);
70 static const GLchan one[4] = { 1.0, 1.0, 1.0, 1.0 };
71 static const GLchan zero[4] = { 0.0, 0.0, 0.0, 0.0 };
72 #else
73 const GLint half = (CHAN_MAX + 1) / 2;
74 static const GLchan one[4] = { CHAN_MAX, CHAN_MAX, CHAN_MAX, CHAN_MAX };
75 static const GLchan zero[4] = { 0, 0, 0, 0 };
76 #endif
77 const GLuint numColorArgs = textureUnit->_CurrentCombine->_NumArgsRGB;
78 const GLuint numAlphaArgs = textureUnit->_CurrentCombine->_NumArgsA;
79 GLchan ccolor[3][MAX_WIDTH][4];
80 GLuint i, j;
81
82 ASSERT(ctx->Extensions.EXT_texture_env_combine ||
83 ctx->Extensions.ARB_texture_env_combine);
84 ASSERT(SWRAST_CONTEXT(ctx)->_AnyTextureCombine);
85
86 /*
87 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
88 textureUnit->_CurrentCombine->ModeRGB,
89 textureUnit->_CurrentCombine->ModeA,
90 textureUnit->_CurrentCombine->SourceRGB[0],
91 textureUnit->_CurrentCombine->SourceA[0],
92 textureUnit->_CurrentCombine->SourceRGB[1],
93 textureUnit->_CurrentCombine->SourceA[1]);
94 */
95
96 /*
97 * Do operand setup for up to 3 operands. Loop over the terms.
98 */
99 for (j = 0; j < numColorArgs; j++) {
100 const GLenum srcRGB = textureUnit->_CurrentCombine->SourceRGB[j];
101
102
103 switch (srcRGB) {
104 case GL_TEXTURE:
105 argRGB[j] = (const GLchan (*)[4])
106 (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
107 break;
108 case GL_PRIMARY_COLOR:
109 argRGB[j] = primary_rgba;
110 break;
111 case GL_PREVIOUS:
112 argRGB[j] = (const GLchan (*)[4]) rgba;
113 break;
114 case GL_CONSTANT:
115 {
116 GLchan (*c)[4] = ccolor[j];
117 GLchan red, green, blue, alpha;
118 UNCLAMPED_FLOAT_TO_CHAN(red, textureUnit->EnvColor[0]);
119 UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
120 UNCLAMPED_FLOAT_TO_CHAN(blue, textureUnit->EnvColor[2]);
121 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
122 for (i = 0; i < n; i++) {
123 c[i][RCOMP] = red;
124 c[i][GCOMP] = green;
125 c[i][BCOMP] = blue;
126 c[i][ACOMP] = alpha;
127 }
128 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
129 }
130 break;
131 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
132 */
133 case GL_ZERO:
134 argRGB[j] = & zero;
135 break;
136 case GL_ONE:
137 argRGB[j] = & one;
138 break;
139 default:
140 /* ARB_texture_env_crossbar source */
141 {
142 const GLuint srcUnit = srcRGB - GL_TEXTURE0;
143 ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
144 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
145 return;
146 argRGB[j] = (const GLchan (*)[4])
147 (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
148 }
149 }
150
151 if (textureUnit->_CurrentCombine->OperandRGB[j] != GL_SRC_COLOR) {
152 const GLchan (*src)[4] = argRGB[j];
153 GLchan (*dst)[4] = ccolor[j];
154
155 /* point to new arg[j] storage */
156 argRGB[j] = (const GLchan (*)[4]) ccolor[j];
157
158 if (textureUnit->_CurrentCombine->OperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
159 for (i = 0; i < n; i++) {
160 dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
161 dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
162 dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
163 }
164 }
165 else if (textureUnit->_CurrentCombine->OperandRGB[j] == GL_SRC_ALPHA) {
166 for (i = 0; i < n; i++) {
167 dst[i][RCOMP] = src[i][ACOMP];
168 dst[i][GCOMP] = src[i][ACOMP];
169 dst[i][BCOMP] = src[i][ACOMP];
170 }
171 }
172 else {
173 ASSERT(textureUnit->_CurrentCombine->OperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
174 for (i = 0; i < n; i++) {
175 dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
176 dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
177 dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
178 }
179 }
180 }
181 }
182
183 /*
184 * Set up the argA[i] pointers
185 */
186 for (j = 0; j < numAlphaArgs; j++) {
187 const GLenum srcA = textureUnit->_CurrentCombine->SourceA[j];
188
189 switch (srcA) {
190 case GL_TEXTURE:
191 argA[j] = (const GLchan (*)[4])
192 (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
193 break;
194 case GL_PRIMARY_COLOR:
195 argA[j] = primary_rgba;
196 break;
197 case GL_PREVIOUS:
198 argA[j] = (const GLchan (*)[4]) rgba;
199 break;
200 case GL_CONSTANT:
201 {
202 GLchan alpha, (*c)[4] = ccolor[j];
203 UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
204 for (i = 0; i < n; i++)
205 c[i][ACOMP] = alpha;
206 argA[j] = (const GLchan (*)[4]) ccolor[j];
207 }
208 break;
209 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
210 */
211 case GL_ZERO:
212 argA[j] = & zero;
213 break;
214 case GL_ONE:
215 argA[j] = & one;
216 break;
217 default:
218 /* ARB_texture_env_crossbar source */
219 {
220 const GLuint srcUnit = srcA - GL_TEXTURE0;
221 ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
222 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
223 return;
224 argA[j] = (const GLchan (*)[4])
225 (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
226 }
227 }
228
229 if (textureUnit->_CurrentCombine->OperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
230 const GLchan (*src)[4] = argA[j];
231 GLchan (*dst)[4] = ccolor[j];
232 argA[j] = (const GLchan (*)[4]) ccolor[j];
233 for (i = 0; i < n; i++) {
234 dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
235 }
236 }
237 }
238
239 /*
240 * Do the texture combine.
241 */
242 switch (textureUnit->_CurrentCombine->ModeRGB) {
243 case GL_REPLACE:
244 {
245 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
246 if (RGBshift) {
247 for (i = 0; i < n; i++) {
248 #if CHAN_TYPE == GL_FLOAT
249 rgba[i][RCOMP] = arg0[i][RCOMP] * RGBmult;
250 rgba[i][GCOMP] = arg0[i][GCOMP] * RGBmult;
251 rgba[i][BCOMP] = arg0[i][BCOMP] * RGBmult;
252 #else
253 GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
254 GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
255 GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
256 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
257 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
258 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
259 #endif
260 }
261 }
262 else {
263 for (i = 0; i < n; i++) {
264 rgba[i][RCOMP] = arg0[i][RCOMP];
265 rgba[i][GCOMP] = arg0[i][GCOMP];
266 rgba[i][BCOMP] = arg0[i][BCOMP];
267 }
268 }
269 }
270 break;
271 case GL_MODULATE:
272 {
273 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
274 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
275 #if CHAN_TYPE != GL_FLOAT
276 const GLint shift = CHAN_BITS - RGBshift;
277 #endif
278 for (i = 0; i < n; i++) {
279 #if CHAN_TYPE == GL_FLOAT
280 rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * RGBmult;
281 rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * RGBmult;
282 rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * RGBmult;
283 #else
284 GLuint r = PROD(arg0[i][RCOMP], arg1[i][RCOMP]) >> shift;
285 GLuint g = PROD(arg0[i][GCOMP], arg1[i][GCOMP]) >> shift;
286 GLuint b = PROD(arg0[i][BCOMP], arg1[i][BCOMP]) >> shift;
287 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
288 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
289 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
290 #endif
291 }
292 }
293 break;
294 case GL_ADD:
295 {
296 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
297 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
298 for (i = 0; i < n; i++) {
299 #if CHAN_TYPE == GL_FLOAT
300 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * RGBmult;
301 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * RGBmult;
302 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * RGBmult;
303 #else
304 GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
305 GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
306 GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
307 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
308 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
309 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
310 #endif
311 }
312 }
313 break;
314 case GL_ADD_SIGNED:
315 {
316 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
317 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
318 for (i = 0; i < n; i++) {
319 #if CHAN_TYPE == GL_FLOAT
320 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * RGBmult;
321 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * RGBmult;
322 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * RGBmult;
323 #else
324 GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] -half;
325 GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] -half;
326 GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] -half;
327 r = (r < 0) ? 0 : r << RGBshift;
328 g = (g < 0) ? 0 : g << RGBshift;
329 b = (b < 0) ? 0 : b << RGBshift;
330 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
331 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
332 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
333 #endif
334 }
335 }
336 break;
337 case GL_INTERPOLATE:
338 {
339 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
340 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
341 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
342 #if CHAN_TYPE != GL_FLOAT
343 const GLint shift = CHAN_BITS - RGBshift;
344 #endif
345 for (i = 0; i < n; i++) {
346 #if CHAN_TYPE == GL_FLOAT
347 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
348 arg1[i][RCOMP] * (CHAN_MAXF - arg2[i][RCOMP])) * RGBmult;
349 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
350 arg1[i][GCOMP] * (CHAN_MAXF - arg2[i][GCOMP])) * RGBmult;
351 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
352 arg1[i][BCOMP] * (CHAN_MAXF - arg2[i][BCOMP])) * RGBmult;
353 #else
354 GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
355 + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
356 >> shift;
357 GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
358 + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
359 >> shift;
360 GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
361 + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
362 >> shift;
363 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
364 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
365 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
366 #endif
367 }
368 }
369 break;
370 case GL_SUBTRACT:
371 {
372 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
373 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
374 for (i = 0; i < n; i++) {
375 #if CHAN_TYPE == GL_FLOAT
376 rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * RGBmult;
377 rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * RGBmult;
378 rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * RGBmult;
379 #else
380 GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
381 GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
382 GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
383 rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
384 rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
385 rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
386 #endif
387 }
388 }
389 break;
390 case GL_DOT3_RGB_EXT:
391 case GL_DOT3_RGBA_EXT:
392 {
393 /* Do not scale the result by 1 2 or 4 */
394 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
395 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
396 for (i = 0; i < n; i++) {
397 #if CHAN_TYPE == GL_FLOAT
398 GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
399 (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
400 (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
401 * 4.0F;
402 dot = CLAMP(dot, 0.0F, CHAN_MAXF);
403 #else
404 GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
405 (GLint)arg1[i][RCOMP] - half) +
406 S_PROD((GLint)arg0[i][GCOMP] - half,
407 (GLint)arg1[i][GCOMP] - half) +
408 S_PROD((GLint)arg0[i][BCOMP] - half,
409 (GLint)arg1[i][BCOMP] - half)) >> 6;
410 dot = CLAMP(dot, 0, CHAN_MAX);
411 #endif
412 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
413 }
414 }
415 break;
416 case GL_DOT3_RGB:
417 case GL_DOT3_RGBA:
418 {
419 /* DO scale the result by 1 2 or 4 */
420 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
421 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
422 for (i = 0; i < n; i++) {
423 #if CHAN_TYPE == GL_FLOAT
424 GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
425 (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
426 (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
427 * 4.0F * RGBmult;
428 dot = CLAMP(dot, 0.0, CHAN_MAXF);
429 #else
430 GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
431 (GLint)arg1[i][RCOMP] - half) +
432 S_PROD((GLint)arg0[i][GCOMP] - half,
433 (GLint)arg1[i][GCOMP] - half) +
434 S_PROD((GLint)arg0[i][BCOMP] - half,
435 (GLint)arg1[i][BCOMP] - half)) >> 6;
436 dot <<= RGBshift;
437 dot = CLAMP(dot, 0, CHAN_MAX);
438 #endif
439 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
440 }
441 }
442 break;
443 case GL_MODULATE_ADD_ATI:
444 {
445 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
446 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
447 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
448 #if CHAN_TYPE != GL_FLOAT
449 const GLint shift = CHAN_BITS - RGBshift;
450 #endif
451 for (i = 0; i < n; i++) {
452 #if CHAN_TYPE == GL_FLOAT
453 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP]) * RGBmult;
454 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP]) * RGBmult;
455 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP]) * RGBmult;
456 #else
457 GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
458 + ((GLuint) arg1[i][RCOMP] << CHAN_BITS)) >> shift;
459 GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
460 + ((GLuint) arg1[i][GCOMP] << CHAN_BITS)) >> shift;
461 GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
462 + ((GLuint) arg1[i][BCOMP] << CHAN_BITS)) >> shift;
463 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
464 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
465 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
466 #endif
467 }
468 }
469 break;
470 case GL_MODULATE_SIGNED_ADD_ATI:
471 {
472 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
473 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
474 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
475 #if CHAN_TYPE != GL_FLOAT
476 const GLint shift = CHAN_BITS - RGBshift;
477 #endif
478 for (i = 0; i < n; i++) {
479 #if CHAN_TYPE == GL_FLOAT
480 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + arg1[i][RCOMP] - 0.5) * RGBmult;
481 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + arg1[i][GCOMP] - 0.5) * RGBmult;
482 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + arg1[i][BCOMP] - 0.5) * RGBmult;
483 #else
484 GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP])
485 + (((GLint) arg1[i][RCOMP] - half) << CHAN_BITS))
486 >> shift;
487 GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP])
488 + (((GLint) arg1[i][GCOMP] - half) << CHAN_BITS))
489 >> shift;
490 GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP])
491 + (((GLint) arg1[i][BCOMP] - half) << CHAN_BITS))
492 >> shift;
493 rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
494 rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
495 rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
496 #endif
497 }
498 }
499 break;
500 case GL_MODULATE_SUBTRACT_ATI:
501 {
502 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
503 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
504 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
505 #if CHAN_TYPE != GL_FLOAT
506 const GLint shift = CHAN_BITS - RGBshift;
507 #endif
508 for (i = 0; i < n; i++) {
509 #if CHAN_TYPE == GL_FLOAT
510 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) - arg1[i][RCOMP]) * RGBmult;
511 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) - arg1[i][GCOMP]) * RGBmult;
512 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) - arg1[i][BCOMP]) * RGBmult;
513 #else
514 GLint r = (S_PROD(arg0[i][RCOMP], arg2[i][RCOMP])
515 - ((GLint) arg1[i][RCOMP] << CHAN_BITS))
516 >> shift;
517 GLint g = (S_PROD(arg0[i][GCOMP], arg2[i][GCOMP])
518 - ((GLint) arg1[i][GCOMP] << CHAN_BITS))
519 >> shift;
520 GLint b = (S_PROD(arg0[i][BCOMP], arg2[i][BCOMP])
521 - ((GLint) arg1[i][BCOMP] << CHAN_BITS))
522 >> shift;
523 rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
524 rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
525 rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
526 #endif
527 }
528 }
529 break;
530 default:
531 _mesa_problem(ctx, "invalid combine mode");
532 }
533
534 switch (textureUnit->_CurrentCombine->ModeA) {
535 case GL_REPLACE:
536 {
537 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
538 if (Ashift) {
539 for (i = 0; i < n; i++) {
540 #if CHAN_TYPE == GL_FLOAT
541 GLchan a = arg0[i][ACOMP] * Amult;
542 #else
543 GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
544 #endif
545 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
546 }
547 }
548 else {
549 for (i = 0; i < n; i++) {
550 rgba[i][ACOMP] = arg0[i][ACOMP];
551 }
552 }
553 }
554 break;
555 case GL_MODULATE:
556 {
557 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
558 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
559 #if CHAN_TYPE != GL_FLOAT
560 const GLint shift = CHAN_BITS - Ashift;
561 #endif
562 for (i = 0; i < n; i++) {
563 #if CHAN_TYPE == GL_FLOAT
564 rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * Amult;
565 #else
566 GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
567 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
568 #endif
569 }
570 }
571 break;
572 case GL_ADD:
573 {
574 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
575 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
576 for (i = 0; i < n; i++) {
577 #if CHAN_TYPE == GL_FLOAT
578 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * Amult;
579 #else
580 GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
581 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
582 #endif
583 }
584 }
585 break;
586 case GL_ADD_SIGNED:
587 {
588 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
589 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
590 for (i = 0; i < n; i++) {
591 #if CHAN_TYPE == GL_FLOAT
592 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * Amult;
593 #else
594 GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] -half;
595 a = (a < 0) ? 0 : a << Ashift;
596 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
597 #endif
598 }
599 }
600 break;
601 case GL_INTERPOLATE:
602 {
603 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
604 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
605 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
606 #if CHAN_TYPE != GL_FLOAT
607 const GLint shift = CHAN_BITS - Ashift;
608 #endif
609 for (i=0; i<n; i++) {
610 #if CHAN_TYPE == GL_FLOAT
611 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
612 arg1[i][ACOMP] * (CHAN_MAXF - arg2[i][ACOMP]))
613 * Amult;
614 #else
615 GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
616 + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
617 >> shift;
618 rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
619 #endif
620 }
621 }
622 break;
623 case GL_SUBTRACT:
624 {
625 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
626 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
627 for (i = 0; i < n; i++) {
628 #if CHAN_TYPE == GL_FLOAT
629 rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * Amult;
630 #else
631 GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << Ashift;
632 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
633 #endif
634 }
635 }
636 break;
637 case GL_MODULATE_ADD_ATI:
638 {
639 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
640 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
641 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
642 #if CHAN_TYPE != GL_FLOAT
643 const GLint shift = CHAN_BITS - Ashift;
644 #endif
645 for (i = 0; i < n; i++) {
646 #if CHAN_TYPE == GL_FLOAT
647 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP]) * Amult;
648 #else
649 GLint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
650 + ((GLuint) arg1[i][ACOMP] << CHAN_BITS))
651 >> shift;
652 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
653 #endif
654 }
655 }
656 break;
657 case GL_MODULATE_SIGNED_ADD_ATI:
658 {
659 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
660 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
661 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
662 #if CHAN_TYPE != GL_FLOAT
663 const GLint shift = CHAN_BITS - Ashift;
664 #endif
665 for (i = 0; i < n; i++) {
666 #if CHAN_TYPE == GL_FLOAT
667 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + arg1[i][ACOMP] - 0.5F) * Amult;
668 #else
669 GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP])
670 + (((GLint) arg1[i][ACOMP] - half) << CHAN_BITS))
671 >> shift;
672 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
673 #endif
674 }
675 }
676 break;
677 case GL_MODULATE_SUBTRACT_ATI:
678 {
679 const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
680 const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
681 const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
682 #if CHAN_TYPE != GL_FLOAT
683 const GLint shift = CHAN_BITS - Ashift;
684 #endif
685 for (i = 0; i < n; i++) {
686 #if CHAN_TYPE == GL_FLOAT
687 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) - arg1[i][ACOMP]) * Amult;
688 #else
689 GLint a = (S_PROD(arg0[i][ACOMP], arg2[i][ACOMP])
690 - ((GLint) arg1[i][ACOMP] << CHAN_BITS))
691 >> shift;
692 rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
693 #endif
694 }
695 }
696 break;
697 default:
698 _mesa_problem(ctx, "invalid combine mode");
699 }
700
701 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
702 * This is kind of a kludge. It would have been better if the spec
703 * were written such that the GL_COMBINE_ALPHA value could be set to
704 * GL_DOT3.
705 */
706 if (textureUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT ||
707 textureUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) {
708 for (i = 0; i < n; i++) {
709 rgba[i][ACOMP] = rgba[i][RCOMP];
710 }
711 }
712 }
713 #undef PROD
714
715
716 /**
717 * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
718 * MODULATE, or DECAL) to an array of fragments.
719 * Input: textureUnit - pointer to texture unit to apply
720 * format - base internal texture format
721 * n - number of fragments
722 * primary_rgba - primary colors (may alias rgba for single texture)
723 * texels - array of texel colors
724 * InOut: rgba - incoming fragment colors modified by texel colors
725 * according to the texture environment mode.
726 */
727 static void
728 texture_apply( const GLcontext *ctx,
729 const struct gl_texture_unit *texUnit,
730 GLuint n,
731 CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
732 GLchan rgba[][4] )
733 {
734 GLint baseLevel;
735 GLuint i;
736 GLint Rc, Gc, Bc, Ac;
737 GLenum format;
738 (void) primary_rgba;
739
740 ASSERT(texUnit);
741 ASSERT(texUnit->_Current);
742
743 baseLevel = texUnit->_Current->BaseLevel;
744 ASSERT(texUnit->_Current->Image[0][baseLevel]);
745
746 format = texUnit->_Current->Image[0][baseLevel]->Format;
747
748 if (format == GL_COLOR_INDEX || format == GL_YCBCR_MESA) {
749 format = GL_RGBA; /* a bit of a hack */
750 }
751 else if (format == GL_DEPTH_COMPONENT) {
752 format = texUnit->_Current->DepthMode;
753 }
754
755 switch (texUnit->EnvMode) {
756 case GL_REPLACE:
757 switch (format) {
758 case GL_ALPHA:
759 for (i=0;i<n;i++) {
760 /* Cv = Cf */
761 /* Av = At */
762 rgba[i][ACOMP] = texel[i][ACOMP];
763 }
764 break;
765 case GL_LUMINANCE:
766 for (i=0;i<n;i++) {
767 /* Cv = Lt */
768 GLchan Lt = texel[i][RCOMP];
769 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
770 /* Av = Af */
771 }
772 break;
773 case GL_LUMINANCE_ALPHA:
774 for (i=0;i<n;i++) {
775 GLchan Lt = texel[i][RCOMP];
776 /* Cv = Lt */
777 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
778 /* Av = At */
779 rgba[i][ACOMP] = texel[i][ACOMP];
780 }
781 break;
782 case GL_INTENSITY:
783 for (i=0;i<n;i++) {
784 /* Cv = It */
785 GLchan It = texel[i][RCOMP];
786 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
787 /* Av = It */
788 rgba[i][ACOMP] = It;
789 }
790 break;
791 case GL_RGB:
792 for (i=0;i<n;i++) {
793 /* Cv = Ct */
794 rgba[i][RCOMP] = texel[i][RCOMP];
795 rgba[i][GCOMP] = texel[i][GCOMP];
796 rgba[i][BCOMP] = texel[i][BCOMP];
797 /* Av = Af */
798 }
799 break;
800 case GL_RGBA:
801 for (i=0;i<n;i++) {
802 /* Cv = Ct */
803 rgba[i][RCOMP] = texel[i][RCOMP];
804 rgba[i][GCOMP] = texel[i][GCOMP];
805 rgba[i][BCOMP] = texel[i][BCOMP];
806 /* Av = At */
807 rgba[i][ACOMP] = texel[i][ACOMP];
808 }
809 break;
810 default:
811 _mesa_problem(ctx, "Bad format (GL_REPLACE) in texture_apply");
812 return;
813 }
814 break;
815
816 case GL_MODULATE:
817 switch (format) {
818 case GL_ALPHA:
819 for (i=0;i<n;i++) {
820 /* Cv = Cf */
821 /* Av = AfAt */
822 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
823 }
824 break;
825 case GL_LUMINANCE:
826 for (i=0;i<n;i++) {
827 /* Cv = LtCf */
828 GLchan Lt = texel[i][RCOMP];
829 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
830 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
831 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
832 /* Av = Af */
833 }
834 break;
835 case GL_LUMINANCE_ALPHA:
836 for (i=0;i<n;i++) {
837 /* Cv = CfLt */
838 GLchan Lt = texel[i][RCOMP];
839 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
840 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
841 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
842 /* Av = AfAt */
843 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
844 }
845 break;
846 case GL_INTENSITY:
847 for (i=0;i<n;i++) {
848 /* Cv = CfIt */
849 GLchan It = texel[i][RCOMP];
850 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
851 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
852 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
853 /* Av = AfIt */
854 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
855 }
856 break;
857 case GL_RGB:
858 for (i=0;i<n;i++) {
859 /* Cv = CfCt */
860 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
861 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
862 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
863 /* Av = Af */
864 }
865 break;
866 case GL_RGBA:
867 for (i=0;i<n;i++) {
868 /* Cv = CfCt */
869 rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
870 rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
871 rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
872 /* Av = AfAt */
873 rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
874 }
875 break;
876 default:
877 _mesa_problem(ctx, "Bad format (GL_MODULATE) in texture_apply");
878 return;
879 }
880 break;
881
882 case GL_DECAL:
883 switch (format) {
884 case GL_ALPHA:
885 case GL_LUMINANCE:
886 case GL_LUMINANCE_ALPHA:
887 case GL_INTENSITY:
888 /* undefined */
889 break;
890 case GL_RGB:
891 for (i=0;i<n;i++) {
892 /* Cv = Ct */
893 rgba[i][RCOMP] = texel[i][RCOMP];
894 rgba[i][GCOMP] = texel[i][GCOMP];
895 rgba[i][BCOMP] = texel[i][BCOMP];
896 /* Av = Af */
897 }
898 break;
899 case GL_RGBA:
900 for (i=0;i<n;i++) {
901 /* Cv = Cf(1-At) + CtAt */
902 GLint t = texel[i][ACOMP], s = CHAN_MAX - t;
903 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
904 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
905 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
906 /* Av = Af */
907 }
908 break;
909 default:
910 _mesa_problem(ctx, "Bad format (GL_DECAL) in texture_apply");
911 return;
912 }
913 break;
914
915 case GL_BLEND:
916 Rc = (GLint) (texUnit->EnvColor[0] * CHAN_MAXF);
917 Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF);
918 Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF);
919 Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF);
920 switch (format) {
921 case GL_ALPHA:
922 for (i=0;i<n;i++) {
923 /* Cv = Cf */
924 /* Av = AfAt */
925 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
926 }
927 break;
928 case GL_LUMINANCE:
929 for (i=0;i<n;i++) {
930 /* Cv = Cf(1-Lt) + CcLt */
931 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
932 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
933 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
934 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
935 /* Av = Af */
936 }
937 break;
938 case GL_LUMINANCE_ALPHA:
939 for (i=0;i<n;i++) {
940 /* Cv = Cf(1-Lt) + CcLt */
941 GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
942 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
943 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
944 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
945 /* Av = AfAt */
946 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
947 }
948 break;
949 case GL_INTENSITY:
950 for (i=0;i<n;i++) {
951 /* Cv = Cf(1-It) + CcIt */
952 GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
953 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
954 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
955 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
956 /* Av = Af(1-It) + Ac*It */
957 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
958 }
959 break;
960 case GL_RGB:
961 for (i=0;i<n;i++) {
962 /* Cv = Cf(1-Ct) + CcCt */
963 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
964 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
965 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
966 /* Av = Af */
967 }
968 break;
969 case GL_RGBA:
970 for (i=0;i<n;i++) {
971 /* Cv = Cf(1-Ct) + CcCt */
972 rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
973 rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
974 rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
975 /* Av = AfAt */
976 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
977 }
978 break;
979 default:
980 _mesa_problem(ctx, "Bad format (GL_BLEND) in texture_apply");
981 return;
982 }
983 break;
984
985 /* XXX don't clamp results if GLchan is float??? */
986
987 case GL_ADD: /* GL_EXT_texture_add_env */
988 switch (format) {
989 case GL_ALPHA:
990 for (i=0;i<n;i++) {
991 /* Rv = Rf */
992 /* Gv = Gf */
993 /* Bv = Bf */
994 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
995 }
996 break;
997 case GL_LUMINANCE:
998 for (i=0;i<n;i++) {
999 GLuint Lt = texel[i][RCOMP];
1000 GLuint r = rgba[i][RCOMP] + Lt;
1001 GLuint g = rgba[i][GCOMP] + Lt;
1002 GLuint b = rgba[i][BCOMP] + Lt;
1003 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1004 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1005 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1006 /* Av = Af */
1007 }
1008 break;
1009 case GL_LUMINANCE_ALPHA:
1010 for (i=0;i<n;i++) {
1011 GLuint Lt = texel[i][RCOMP];
1012 GLuint r = rgba[i][RCOMP] + Lt;
1013 GLuint g = rgba[i][GCOMP] + Lt;
1014 GLuint b = rgba[i][BCOMP] + Lt;
1015 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1016 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1017 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1018 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
1019 }
1020 break;
1021 case GL_INTENSITY:
1022 for (i=0;i<n;i++) {
1023 GLchan It = texel[i][RCOMP];
1024 GLuint r = rgba[i][RCOMP] + It;
1025 GLuint g = rgba[i][GCOMP] + It;
1026 GLuint b = rgba[i][BCOMP] + It;
1027 GLuint a = rgba[i][ACOMP] + It;
1028 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1029 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1030 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1031 rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
1032 }
1033 break;
1034 case GL_RGB:
1035 for (i=0;i<n;i++) {
1036 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
1037 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
1038 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
1039 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1040 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1041 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1042 /* Av = Af */
1043 }
1044 break;
1045 case GL_RGBA:
1046 for (i=0;i<n;i++) {
1047 GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
1048 GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
1049 GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
1050 rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
1051 rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
1052 rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
1053 rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
1054 }
1055 break;
1056 default:
1057 _mesa_problem(ctx, "Bad format (GL_ADD) in texture_apply");
1058 return;
1059 }
1060 break;
1061
1062 default:
1063 _mesa_problem(ctx, "Bad env mode in texture_apply");
1064 return;
1065 }
1066 }
1067
1068
1069
1070 /**
1071 * Apply texture mapping to a span of fragments.
1072 */
1073 void
1074 _swrast_texture_span( GLcontext *ctx, struct sw_span *span )
1075 {
1076 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1077 GLchan primary_rgba[MAX_WIDTH][4];
1078 GLuint unit;
1079
1080 ASSERT(span->end < MAX_WIDTH);
1081 ASSERT(span->arrayMask & SPAN_TEXTURE);
1082
1083 /*
1084 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
1085 */
1086 if (swrast->_AnyTextureCombine)
1087 MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan));
1088
1089 /*
1090 * Must do all texture sampling before combining in order to
1091 * accomodate GL_ARB_texture_env_crossbar.
1092 */
1093 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1094 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
1095 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1096 const struct gl_texture_object *curObj = texUnit->_Current;
1097 GLfloat *lambda = span->array->lambda[unit];
1098 GLchan (*texels)[4] = (GLchan (*)[4])
1099 (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan)));
1100
1101 /* adjust texture lod (lambda) */
1102 if (span->arrayMask & SPAN_LAMBDA) {
1103 if (texUnit->LodBias + curObj->LodBias != 0.0F) {
1104 /* apply LOD bias, but don't clamp yet */
1105 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
1106 -ctx->Const.MaxTextureLodBias,
1107 ctx->Const.MaxTextureLodBias);
1108 GLuint i;
1109 for (i = 0; i < span->end; i++) {
1110 lambda[i] += bias;
1111 }
1112 }
1113
1114 if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
1115 /* apply LOD clamping to lambda */
1116 const GLfloat min = curObj->MinLod;
1117 const GLfloat max = curObj->MaxLod;
1118 GLuint i;
1119 for (i = 0; i < span->end; i++) {
1120 GLfloat l = lambda[i];
1121 lambda[i] = CLAMP(l, min, max);
1122 }
1123 }
1124 }
1125
1126 /* Sample the texture (span->end = number of fragments) */
1127 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
1128 (const GLfloat (*)[4]) span->array->texcoords[unit],
1129 lambda, texels );
1130
1131 /* GL_SGI_texture_color_table */
1132 if (texUnit->ColorTableEnabled) {
1133 _mesa_lookup_rgba_chan(&texUnit->ColorTable, span->end, texels);
1134 }
1135 }
1136 }
1137
1138 /*
1139 * OK, now apply the texture (aka texture combine/blend).
1140 * We modify the span->color.rgba values.
1141 */
1142 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1143 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
1144 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1145 if (texUnit->_CurrentCombine != &texUnit->_EnvMode ) {
1146 texture_combine( ctx, unit, span->end,
1147 (CONST GLchan (*)[4]) primary_rgba,
1148 swrast->TexelBuffer,
1149 span->array->rgba );
1150 }
1151 else {
1152 /* conventional texture blend */
1153 const GLchan (*texels)[4] = (const GLchan (*)[4])
1154 (swrast->TexelBuffer + unit *
1155 (span->end * 4 * sizeof(GLchan)));
1156 texture_apply( ctx, texUnit, span->end,
1157 (CONST GLchan (*)[4]) primary_rgba, texels,
1158 span->array->rgba );
1159 }
1160 }
1161 }
1162 }