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