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