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