swrast: asst. clean-ups in texcombine code
[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/pixel.h"
33 #include "shader/prog_instruction.h"
34
35 #include "s_context.h"
36 #include "s_texcombine.h"
37
38
39 /**
40 * Pointer to array of float[4]
41 * This type makes the code below more concise and avoids a lot of casting.
42 */
43 typedef float (*float4_array)[4];
44
45
46 /**
47 * Return array of texels for given unit.
48 */
49 static INLINE float4_array
50 get_texel_array(SWcontext *swrast, GLuint unit)
51 {
52 return (float4_array)
53 (swrast->TexelBuffer + unit * MAX_WIDTH * 4 * sizeof(GLfloat));
54 }
55
56
57
58 /**
59 * Do texture application for:
60 * GL_EXT_texture_env_combine
61 * GL_ARB_texture_env_combine
62 * GL_EXT_texture_env_dot3
63 * GL_ARB_texture_env_dot3
64 * GL_ATI_texture_env_combine3
65 * GL_NV_texture_env_combine4
66 * conventional GL texture env modes
67 *
68 * \param ctx rendering context
69 * \param unit the texture combiner unit
70 * \param n number of fragments to process (span width)
71 * \param primary_rgba incoming fragment color array
72 * \param texelBuffer pointer to texel colors for all texture units
73 *
74 * \param rgba incoming/result fragment colors
75 */
76 static void
77 texture_combine( GLcontext *ctx, GLuint unit, GLuint n,
78 const float4_array primary_rgba,
79 const GLfloat *texelBuffer,
80 GLchan (*rgbaChan)[4] )
81 {
82 SWcontext *swrast = SWRAST_CONTEXT(ctx);
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 for (i = 0; i < n; i++) {
96 rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
97 rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
98 rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
99 rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
100 }
101
102 /*
103 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
104 combine->ModeRGB,
105 combine->ModeA,
106 combine->SourceRGB[0],
107 combine->SourceA[0],
108 combine->SourceRGB[1],
109 combine->SourceA[1]);
110 */
111
112 /*
113 * Do operand setup for up to 4 operands. Loop over the terms.
114 */
115 for (term = 0; term < numArgsRGB; term++) {
116 const GLenum srcRGB = combine->SourceRGB[term];
117 const GLenum operandRGB = combine->OperandRGB[term];
118
119 switch (srcRGB) {
120 case GL_TEXTURE:
121 argRGB[term] = get_texel_array(swrast, unit);
122 break;
123 case GL_PRIMARY_COLOR:
124 argRGB[term] = primary_rgba;
125 break;
126 case GL_PREVIOUS:
127 argRGB[term] = rgba;
128 break;
129 case GL_CONSTANT:
130 {
131 float4_array c = ccolor[term];
132 GLfloat red = textureUnit->EnvColor[0];
133 GLfloat green = textureUnit->EnvColor[1];
134 GLfloat blue = textureUnit->EnvColor[2];
135 GLfloat alpha = textureUnit->EnvColor[3];
136 for (i = 0; i < n; i++) {
137 ASSIGN_4V(c[i], red, green, blue, alpha);
138 }
139 argRGB[term] = ccolor[term];
140 }
141 break;
142 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
143 */
144 case GL_ZERO:
145 {
146 float4_array c = ccolor[term];
147 for (i = 0; i < n; i++) {
148 ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
149 }
150 argRGB[term] = ccolor[term];
151 }
152 break;
153 case GL_ONE:
154 {
155 float4_array c = ccolor[term];
156 for (i = 0; i < n; i++) {
157 ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
158 }
159 argRGB[term] = ccolor[term];
160 }
161 break;
162 default:
163 /* ARB_texture_env_crossbar source */
164 {
165 const GLuint srcUnit = srcRGB - GL_TEXTURE0;
166 ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
167 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
168 return;
169 argRGB[term] = get_texel_array(swrast, srcUnit);
170 }
171 }
172
173 if (operandRGB != GL_SRC_COLOR) {
174 float4_array src = argRGB[term];
175 float4_array dst = ccolor[term];
176
177 /* point to new arg[term] storage */
178 argRGB[term] = ccolor[term];
179
180 switch (operandRGB) {
181 case GL_ONE_MINUS_SRC_COLOR:
182 for (i = 0; i < n; i++) {
183 dst[i][RCOMP] = 1.0F - src[i][RCOMP];
184 dst[i][GCOMP] = 1.0F - src[i][GCOMP];
185 dst[i][BCOMP] = 1.0F - src[i][BCOMP];
186 }
187 break;
188 case GL_SRC_ALPHA:
189 for (i = 0; i < n; i++) {
190 dst[i][RCOMP] =
191 dst[i][GCOMP] =
192 dst[i][BCOMP] = src[i][ACOMP];
193 }
194 break;
195 case GL_ONE_MINUS_SRC_ALPHA:
196 for (i = 0; i < n; i++) {
197 dst[i][RCOMP] =
198 dst[i][GCOMP] =
199 dst[i][BCOMP] = 1.0F - src[i][ACOMP];
200 }
201 break;
202 default:
203 _mesa_problem(ctx, "Bad operandRGB");
204 }
205 }
206 }
207
208 /*
209 * Set up the argA[term] pointers
210 */
211 for (term = 0; term < numArgsA; term++) {
212 const GLenum srcA = combine->SourceA[term];
213 const GLenum operandA = combine->OperandA[term];
214
215 switch (srcA) {
216 case GL_TEXTURE:
217 argA[term] = get_texel_array(swrast, unit);
218 break;
219 case GL_PRIMARY_COLOR:
220 argA[term] = primary_rgba;
221 break;
222 case GL_PREVIOUS:
223 argA[term] = rgba;
224 break;
225 case GL_CONSTANT:
226 {
227 float4_array c = ccolor[term];
228 GLfloat alpha = textureUnit->EnvColor[3];
229 for (i = 0; i < n; i++)
230 c[i][ACOMP] = alpha;
231 argA[term] = ccolor[term];
232 }
233 break;
234 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
235 */
236 case GL_ZERO:
237 {
238 float4_array c = ccolor[term];
239 for (i = 0; i < n; i++)
240 c[i][ACOMP] = 0.0F;
241 argA[term] = ccolor[term];
242 }
243 break;
244 case GL_ONE:
245 {
246 float4_array c = ccolor[term];
247 for (i = 0; i < n; i++)
248 c[i][ACOMP] = 1.0F;
249 argA[term] = ccolor[term];
250 }
251 break;
252 default:
253 /* ARB_texture_env_crossbar source */
254 {
255 const GLuint srcUnit = srcA - GL_TEXTURE0;
256 ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
257 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
258 return;
259 argA[term] = get_texel_array(swrast, srcUnit);
260 }
261 }
262
263 if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
264 float4_array src = argA[term];
265 float4_array dst = ccolor[term];
266 argA[term] = ccolor[term];
267 for (i = 0; i < n; i++) {
268 dst[i][ACOMP] = 1.0F - src[i][ACOMP];
269 }
270 }
271 }
272
273 /* RGB channel combine */
274 {
275 float4_array arg0 = argRGB[0];
276 float4_array arg1 = argRGB[1];
277 float4_array arg2 = argRGB[2];
278 float4_array arg3 = argRGB[3];
279
280 switch (combine->ModeRGB) {
281 case GL_REPLACE:
282 for (i = 0; i < n; i++) {
283 rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
284 rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
285 rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
286 }
287 break;
288 case GL_MODULATE:
289 for (i = 0; i < n; i++) {
290 rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
291 rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
292 rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
293 }
294 break;
295 case GL_ADD:
296 if (textureUnit->EnvMode == GL_COMBINE4_NV) {
297 /* (a * b) + (c * d) */
298 for (i = 0; i < n; i++) {
299 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
300 arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
301 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
302 arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
303 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
304 arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
305 }
306 }
307 else {
308 /* 2-term addition */
309 for (i = 0; i < n; i++) {
310 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
311 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
312 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
313 }
314 }
315 break;
316 case GL_ADD_SIGNED:
317 if (textureUnit->EnvMode == GL_COMBINE4_NV) {
318 /* (a * b) + (c * d) - 0.5 */
319 for (i = 0; i < n; i++) {
320 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
321 arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5) * scaleRGB;
322 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
323 arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5) * scaleRGB;
324 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
325 arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5) * scaleRGB;
326 }
327 }
328 else {
329 for (i = 0; i < n; i++) {
330 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * scaleRGB;
331 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * scaleRGB;
332 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * scaleRGB;
333 }
334 }
335 break;
336 case GL_INTERPOLATE:
337 for (i = 0; i < n; i++) {
338 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
339 arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
340 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
341 arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
342 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
343 arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
344 }
345 break;
346 case GL_SUBTRACT:
347 for (i = 0; i < n; i++) {
348 rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
349 rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
350 rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
351 }
352 break;
353 case GL_DOT3_RGB_EXT:
354 case GL_DOT3_RGBA_EXT:
355 /* Do not scale the result by 1 2 or 4 */
356 for (i = 0; i < n; i++) {
357 GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
358 (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
359 (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
360 * 4.0F;
361 dot = CLAMP(dot, 0.0F, 1.0F);
362 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
363 }
364 break;
365 case GL_DOT3_RGB:
366 case GL_DOT3_RGBA:
367 /* DO scale the result by 1 2 or 4 */
368 for (i = 0; i < n; i++) {
369 GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
370 (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
371 (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
372 * 4.0F * scaleRGB;
373 dot = CLAMP(dot, 0.0, 1.0F);
374 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
375 }
376 break;
377 case GL_MODULATE_ADD_ATI:
378 for (i = 0; i < n; i++) {
379 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
380 arg1[i][RCOMP]) * scaleRGB;
381 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
382 arg1[i][GCOMP]) * scaleRGB;
383 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
384 arg1[i][BCOMP]) * scaleRGB;
385 }
386 break;
387 case GL_MODULATE_SIGNED_ADD_ATI:
388 for (i = 0; i < n; i++) {
389 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
390 arg1[i][RCOMP] - 0.5) * scaleRGB;
391 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
392 arg1[i][GCOMP] - 0.5) * scaleRGB;
393 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
394 arg1[i][BCOMP] - 0.5) * scaleRGB;
395 }
396 break;
397 case GL_MODULATE_SUBTRACT_ATI:
398 for (i = 0; i < n; i++) {
399 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
400 arg1[i][RCOMP]) * scaleRGB;
401 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
402 arg1[i][GCOMP]) * scaleRGB;
403 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
404 arg1[i][BCOMP]) * scaleRGB;
405 }
406 break;
407 case GL_BUMP_ENVMAP_ATI:
408 {
409 /* this produces a fixed rgba color, and the coord calc is done elsewhere */
410 for (i = 0; i < n; i++) {
411 /* rgba result is 0,0,0,1 */
412 #if CHAN_TYPE == GL_FLOAT
413 rgba[i][RCOMP] = 0.0;
414 rgba[i][GCOMP] = 0.0;
415 rgba[i][BCOMP] = 0.0;
416 rgba[i][ACOMP] = 1.0;
417 #else
418 rgba[i][RCOMP] = 0;
419 rgba[i][GCOMP] = 0;
420 rgba[i][BCOMP] = 0;
421 rgba[i][ACOMP] = CHAN_MAX;
422 #endif
423 }
424 }
425 return; /* no alpha processing */
426 default:
427 _mesa_problem(ctx, "invalid combine mode");
428 }
429 }
430
431 /* Alpha channel combine */
432 {
433 float4_array arg0 = argA[0];
434 float4_array arg1 = argA[1];
435 float4_array arg2 = argA[2];
436 float4_array arg3 = argA[3];
437
438 switch (combine->ModeA) {
439 case GL_REPLACE:
440 for (i = 0; i < n; i++) {
441 rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
442 }
443 break;
444 case GL_MODULATE:
445 for (i = 0; i < n; i++) {
446 rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
447 }
448 break;
449 case GL_ADD:
450 if (textureUnit->EnvMode == GL_COMBINE4_NV) {
451 /* (a * b) + (c * d) */
452 for (i = 0; i < n; i++) {
453 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
454 arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
455 }
456 }
457 else {
458 /* two-term add */
459 for (i = 0; i < n; i++) {
460 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
461 }
462 }
463 break;
464 case GL_ADD_SIGNED:
465 if (textureUnit->EnvMode == GL_COMBINE4_NV) {
466 /* (a * b) + (c * d) - 0.5 */
467 for (i = 0; i < n; i++) {
468 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
469 arg2[i][ACOMP] * arg3[i][ACOMP] -
470 0.5) * scaleA;
471 }
472 }
473 else {
474 /* a + b - 0.5 */
475 for (i = 0; i < n; i++) {
476 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
477 }
478 }
479 break;
480 case GL_INTERPOLATE:
481 for (i = 0; i < n; i++) {
482 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
483 arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
484 * scaleA;
485 }
486 break;
487 case GL_SUBTRACT:
488 for (i = 0; i < n; i++) {
489 rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
490 }
491 break;
492 case GL_MODULATE_ADD_ATI:
493 for (i = 0; i < n; i++) {
494 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
495 + arg1[i][ACOMP]) * scaleA;
496 }
497 break;
498 case GL_MODULATE_SIGNED_ADD_ATI:
499 for (i = 0; i < n; i++) {
500 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
501 arg1[i][ACOMP] - 0.5F) * scaleA;
502 }
503 break;
504 case GL_MODULATE_SUBTRACT_ATI:
505 for (i = 0; i < n; i++) {
506 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
507 - arg1[i][ACOMP]) * scaleA;
508 }
509 break;
510 default:
511 _mesa_problem(ctx, "invalid combine mode");
512 }
513 }
514
515 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
516 * This is kind of a kludge. It would have been better if the spec
517 * were written such that the GL_COMBINE_ALPHA value could be set to
518 * GL_DOT3.
519 */
520 if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
521 combine->ModeRGB == GL_DOT3_RGBA) {
522 for (i = 0; i < n; i++) {
523 rgba[i][ACOMP] = rgba[i][RCOMP];
524 }
525 }
526
527 for (i = 0; i < n; i++) {
528 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
529 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
530 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
531 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
532 }
533 }
534
535
536 /**
537 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
538 * See GL_EXT_texture_swizzle.
539 */
540 static void
541 swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
542 {
543 const GLuint swzR = GET_SWZ(swizzle, 0);
544 const GLuint swzG = GET_SWZ(swizzle, 1);
545 const GLuint swzB = GET_SWZ(swizzle, 2);
546 const GLuint swzA = GET_SWZ(swizzle, 3);
547 GLfloat vector[6];
548 GLuint i;
549
550 vector[SWIZZLE_ZERO] = 0;
551 vector[SWIZZLE_ONE] = 1.0F;
552
553 for (i = 0; i < count; i++) {
554 vector[SWIZZLE_X] = texels[i][0];
555 vector[SWIZZLE_Y] = texels[i][1];
556 vector[SWIZZLE_Z] = texels[i][2];
557 vector[SWIZZLE_W] = texels[i][3];
558 texels[i][RCOMP] = vector[swzR];
559 texels[i][GCOMP] = vector[swzG];
560 texels[i][BCOMP] = vector[swzB];
561 texels[i][ACOMP] = vector[swzA];
562 }
563 }
564
565
566 /**
567 * Apply texture mapping to a span of fragments.
568 */
569 void
570 _swrast_texture_span( GLcontext *ctx, SWspan *span )
571 {
572 SWcontext *swrast = SWRAST_CONTEXT(ctx);
573 GLfloat primary_rgba[MAX_WIDTH][4];
574 GLuint unit;
575
576 ASSERT(span->end <= MAX_WIDTH);
577
578 /*
579 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
580 */
581 if (swrast->_TextureCombinePrimary) {
582 GLuint i;
583 for (i = 0; i < span->end; i++) {
584 primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
585 primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
586 primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
587 primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
588 }
589 }
590
591 /* First must sample all bump maps */
592 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
593 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
594
595 if (texUnit->_ReallyEnabled &&
596 texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
597 const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
598 span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
599 float4_array targetcoords =
600 span->array->attribs[FRAG_ATTRIB_TEX0 +
601 ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
602
603 const struct gl_texture_object *curObj = texUnit->_Current;
604 GLfloat *lambda = span->array->lambda[unit];
605 float4_array texels = get_texel_array(swrast, unit);
606 GLuint i;
607 GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
608 GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
609 GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
610 GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];
611
612 /* adjust texture lod (lambda) */
613 if (span->arrayMask & SPAN_LAMBDA) {
614 if (texUnit->LodBias + curObj->LodBias != 0.0F) {
615 /* apply LOD bias, but don't clamp yet */
616 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
617 -ctx->Const.MaxTextureLodBias,
618 ctx->Const.MaxTextureLodBias);
619 GLuint i;
620 for (i = 0; i < span->end; i++) {
621 lambda[i] += bias;
622 }
623 }
624
625 if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
626 /* apply LOD clamping to lambda */
627 const GLfloat min = curObj->MinLod;
628 const GLfloat max = curObj->MaxLod;
629 GLuint i;
630 for (i = 0; i < span->end; i++) {
631 GLfloat l = lambda[i];
632 lambda[i] = CLAMP(l, min, max);
633 }
634 }
635 }
636
637 /* Sample the texture (span->end = number of fragments) */
638 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
639 texcoords, lambda, texels );
640
641 /* manipulate the span values of the bump target
642 not sure this can work correctly even ignoring
643 the problem that channel is unsigned */
644 for (i = 0; i < span->end; i++) {
645 #if CHAN_TYPE == GL_FLOAT
646 targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
647 rotMatrix01) / targetcoords[i][3];
648 targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
649 rotMatrix11) / targetcoords[i][3];
650 #else
651 targetcoords[i][0] += (CHAN_TO_FLOAT(texels[i][1]) * rotMatrix00 +
652 CHAN_TO_FLOAT(texels[i][1]) * rotMatrix01) /
653 targetcoords[i][3];
654 targetcoords[i][1] += (CHAN_TO_FLOAT(texels[i][0]) * rotMatrix10 +
655 CHAN_TO_FLOAT(texels[i][1]) * rotMatrix11) /
656 targetcoords[i][3];
657 #endif
658 }
659 }
660 }
661
662 /*
663 * Must do all texture sampling before combining in order to
664 * accomodate GL_ARB_texture_env_crossbar.
665 */
666 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
667 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
668 if (texUnit->_ReallyEnabled &&
669 texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
670 const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
671 span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
672 const struct gl_texture_object *curObj = texUnit->_Current;
673 GLfloat *lambda = span->array->lambda[unit];
674 float4_array texels = get_texel_array(swrast, unit);
675
676 /* adjust texture lod (lambda) */
677 if (span->arrayMask & SPAN_LAMBDA) {
678 if (texUnit->LodBias + curObj->LodBias != 0.0F) {
679 /* apply LOD bias, but don't clamp yet */
680 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
681 -ctx->Const.MaxTextureLodBias,
682 ctx->Const.MaxTextureLodBias);
683 GLuint i;
684 for (i = 0; i < span->end; i++) {
685 lambda[i] += bias;
686 }
687 }
688
689 if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
690 /* apply LOD clamping to lambda */
691 const GLfloat min = curObj->MinLod;
692 const GLfloat max = curObj->MaxLod;
693 GLuint i;
694 for (i = 0; i < span->end; i++) {
695 GLfloat l = lambda[i];
696 lambda[i] = CLAMP(l, min, max);
697 }
698 }
699 }
700
701 /* Sample the texture (span->end = number of fragments) */
702 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
703 texcoords, lambda, texels );
704
705 /* GL_SGI_texture_color_table */
706 if (texUnit->ColorTableEnabled) {
707 _mesa_lookup_rgba_float(&texUnit->ColorTable, span->end, texels);
708 }
709
710 /* GL_EXT_texture_swizzle */
711 if (curObj->_Swizzle != SWIZZLE_NOOP) {
712 swizzle_texels(curObj->_Swizzle, span->end, texels);
713 }
714 }
715 }
716
717 /*
718 * OK, now apply the texture (aka texture combine/blend).
719 * We modify the span->color.rgba values.
720 */
721 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
722 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
723 texture_combine( ctx, unit, span->end,
724 primary_rgba,
725 swrast->TexelBuffer,
726 span->array->rgba );
727 }
728 }
729 }