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