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