2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
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.
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"
35 #include "s_context.h"
36 #include "s_texcombine.h"
40 * Pointer to array of float[4]
41 * This type makes the code below more concise and avoids a lot of casting.
43 typedef float (*float4_array
)[4];
47 * Return array of texels for given unit.
49 static INLINE float4_array
50 get_texel_array(const GLfloat
*texelBuffer
, GLuint unit
, GLuint numTexels
)
53 (texelBuffer
+ unit
* numTexels
* 4 * sizeof(GLfloat
));
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
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
74 * \param rgba incoming/result fragment colors
77 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
78 const float4_array primary_rgba
,
79 const GLfloat
*texelBuffer
,
80 GLchan (*rgbaChan
)[4] )
82 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
83 const struct gl_tex_env_combine_state
*combine
= textureUnit
->_CurrentCombine
;
84 float4_array argRGB
[MAX_COMBINER_TERMS
];
85 float4_array argA
[MAX_COMBINER_TERMS
];
86 const GLfloat scaleRGB
= (GLfloat
) (1 << combine
->ScaleShiftRGB
);
87 const GLfloat scaleA
= (GLfloat
) (1 << combine
->ScaleShiftA
);
88 const GLuint numArgsRGB
= combine
->_NumArgsRGB
;
89 const GLuint numArgsA
= combine
->_NumArgsA
;
90 GLfloat ccolor
[MAX_COMBINER_TERMS
][MAX_WIDTH
][4]; /* temp color buffers */
91 GLfloat rgba
[MAX_WIDTH
][4];
94 for (i
= 0; i
< n
; i
++) {
95 rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][RCOMP
]);
96 rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][GCOMP
]);
97 rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][BCOMP
]);
98 rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][ACOMP
]);
102 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
105 combine->SourceRGB[0],
107 combine->SourceRGB[1],
108 combine->SourceA[1]);
112 * Do operand setup for up to 4 operands. Loop over the terms.
114 for (term
= 0; term
< numArgsRGB
; term
++) {
115 const GLenum srcRGB
= combine
->SourceRGB
[term
];
116 const GLenum operandRGB
= combine
->OperandRGB
[term
];
120 argRGB
[term
] = get_texel_array(texelBuffer
, unit
, n
);
122 case GL_PRIMARY_COLOR
:
123 argRGB
[term
] = primary_rgba
;
130 float4_array c
= ccolor
[term
];
131 GLfloat red
= textureUnit
->EnvColor
[0];
132 GLfloat green
= textureUnit
->EnvColor
[1];
133 GLfloat blue
= textureUnit
->EnvColor
[2];
134 GLfloat alpha
= textureUnit
->EnvColor
[3];
135 for (i
= 0; i
< n
; i
++) {
136 ASSIGN_4V(c
[i
], red
, green
, blue
, alpha
);
138 argRGB
[term
] = ccolor
[term
];
141 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
145 float4_array c
= ccolor
[term
];
146 for (i
= 0; i
< n
; i
++) {
147 ASSIGN_4V(c
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
149 argRGB
[term
] = ccolor
[term
];
154 float4_array c
= ccolor
[term
];
155 for (i
= 0; i
< n
; i
++) {
156 ASSIGN_4V(c
[i
], 1.0F
, 1.0F
, 1.0F
, 1.0F
);
158 argRGB
[term
] = ccolor
[term
];
162 /* ARB_texture_env_crossbar source */
164 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
165 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
166 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
168 argRGB
[term
] = get_texel_array(texelBuffer
, srcUnit
, n
);
172 if (operandRGB
!= GL_SRC_COLOR
) {
173 float4_array src
= argRGB
[term
];
174 float4_array dst
= ccolor
[term
];
176 /* point to new arg[term] storage */
177 argRGB
[term
] = ccolor
[term
];
179 switch (operandRGB
) {
180 case GL_ONE_MINUS_SRC_COLOR
:
181 for (i
= 0; i
< n
; i
++) {
182 dst
[i
][RCOMP
] = 1.0F
- src
[i
][RCOMP
];
183 dst
[i
][GCOMP
] = 1.0F
- src
[i
][GCOMP
];
184 dst
[i
][BCOMP
] = 1.0F
- src
[i
][BCOMP
];
188 for (i
= 0; i
< n
; i
++) {
191 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
194 case GL_ONE_MINUS_SRC_ALPHA
:
195 for (i
= 0; i
< n
; i
++) {
198 dst
[i
][BCOMP
] = 1.0F
- src
[i
][ACOMP
];
202 _mesa_problem(ctx
, "Bad operandRGB");
208 * Set up the argA[term] pointers
210 for (term
= 0; term
< numArgsA
; term
++) {
211 const GLenum srcA
= combine
->SourceA
[term
];
212 const GLenum operandA
= combine
->OperandA
[term
];
216 argA
[term
] = get_texel_array(texelBuffer
, unit
, n
);
218 case GL_PRIMARY_COLOR
:
219 argA
[term
] = primary_rgba
;
226 float4_array c
= ccolor
[term
];
227 GLfloat alpha
= textureUnit
->EnvColor
[3];
228 for (i
= 0; i
< n
; i
++)
230 argA
[term
] = ccolor
[term
];
233 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
237 float4_array c
= ccolor
[term
];
238 for (i
= 0; i
< n
; i
++)
240 argA
[term
] = ccolor
[term
];
245 float4_array c
= ccolor
[term
];
246 for (i
= 0; i
< n
; i
++)
248 argA
[term
] = ccolor
[term
];
252 /* ARB_texture_env_crossbar source */
254 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
255 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
256 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
258 argA
[term
] = get_texel_array(texelBuffer
, srcUnit
, n
);
262 if (operandA
== GL_ONE_MINUS_SRC_ALPHA
) {
263 float4_array src
= argA
[term
];
264 float4_array dst
= ccolor
[term
];
265 argA
[term
] = ccolor
[term
];
266 for (i
= 0; i
< n
; i
++) {
267 dst
[i
][ACOMP
] = 1.0F
- src
[i
][ACOMP
];
272 /* RGB channel combine */
274 float4_array arg0
= argRGB
[0];
275 float4_array arg1
= argRGB
[1];
276 float4_array arg2
= argRGB
[2];
277 float4_array arg3
= argRGB
[3];
279 switch (combine
->ModeRGB
) {
281 for (i
= 0; i
< n
; i
++) {
282 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * scaleRGB
;
283 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * scaleRGB
;
284 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * scaleRGB
;
288 for (i
= 0; i
< n
; i
++) {
289 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * scaleRGB
;
290 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * scaleRGB
;
291 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * scaleRGB
;
295 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
296 /* (a * b) + (c * d) */
297 for (i
= 0; i
< n
; i
++) {
298 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
299 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
]) * scaleRGB
;
300 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
301 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
]) * scaleRGB
;
302 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
303 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
]) * scaleRGB
;
307 /* 2-term addition */
308 for (i
= 0; i
< n
; i
++) {
309 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * scaleRGB
;
310 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * scaleRGB
;
311 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * scaleRGB
;
316 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
317 /* (a * b) + (c * d) - 0.5 */
318 for (i
= 0; i
< n
; i
++) {
319 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] *
320 arg2
[i
][RCOMP
] + arg3
[i
][RCOMP
] - 0.5) * scaleRGB
;
321 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] *
322 arg2
[i
][GCOMP
] + arg3
[i
][GCOMP
] - 0.5) * scaleRGB
;
323 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] *
324 arg2
[i
][BCOMP
] + arg3
[i
][BCOMP
] - 0.5) * scaleRGB
;
328 for (i
= 0; i
< n
; i
++) {
329 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5) * scaleRGB
;
330 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5) * scaleRGB
;
331 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5) * scaleRGB
;
336 for (i
= 0; i
< n
; i
++) {
337 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
338 arg1
[i
][RCOMP
] * (1.0F
- arg2
[i
][RCOMP
])) * scaleRGB
;
339 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
340 arg1
[i
][GCOMP
] * (1.0F
- arg2
[i
][GCOMP
])) * scaleRGB
;
341 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
342 arg1
[i
][BCOMP
] * (1.0F
- arg2
[i
][BCOMP
])) * scaleRGB
;
346 for (i
= 0; i
< n
; i
++) {
347 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * scaleRGB
;
348 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * scaleRGB
;
349 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * scaleRGB
;
352 case GL_DOT3_RGB_EXT
:
353 case GL_DOT3_RGBA_EXT
:
354 /* Do not scale the result by 1 2 or 4 */
355 for (i
= 0; i
< n
; i
++) {
356 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
357 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
358 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
360 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
361 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
366 /* DO scale the result by 1 2 or 4 */
367 for (i
= 0; i
< n
; i
++) {
368 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
369 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
370 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
372 dot
= CLAMP(dot
, 0.0, 1.0F
);
373 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
376 case GL_MODULATE_ADD_ATI
:
377 for (i
= 0; i
< n
; i
++) {
378 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
379 arg1
[i
][RCOMP
]) * scaleRGB
;
380 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
381 arg1
[i
][GCOMP
]) * scaleRGB
;
382 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
383 arg1
[i
][BCOMP
]) * scaleRGB
;
386 case GL_MODULATE_SIGNED_ADD_ATI
:
387 for (i
= 0; i
< n
; i
++) {
388 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
389 arg1
[i
][RCOMP
] - 0.5) * scaleRGB
;
390 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
391 arg1
[i
][GCOMP
] - 0.5) * scaleRGB
;
392 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
393 arg1
[i
][BCOMP
] - 0.5) * scaleRGB
;
396 case GL_MODULATE_SUBTRACT_ATI
:
397 for (i
= 0; i
< n
; i
++) {
398 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) -
399 arg1
[i
][RCOMP
]) * scaleRGB
;
400 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) -
401 arg1
[i
][GCOMP
]) * scaleRGB
;
402 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) -
403 arg1
[i
][BCOMP
]) * scaleRGB
;
406 case GL_BUMP_ENVMAP_ATI
:
408 /* this produces a fixed rgba color, and the coord calc is done elsewhere */
409 for (i
= 0; i
< n
; i
++) {
410 /* rgba result is 0,0,0,1 */
411 #if CHAN_TYPE == GL_FLOAT
412 rgba
[i
][RCOMP
] = 0.0;
413 rgba
[i
][GCOMP
] = 0.0;
414 rgba
[i
][BCOMP
] = 0.0;
415 rgba
[i
][ACOMP
] = 1.0;
420 rgba
[i
][ACOMP
] = CHAN_MAX
;
424 return; /* no alpha processing */
426 _mesa_problem(ctx
, "invalid combine mode");
430 /* Alpha channel combine */
432 float4_array arg0
= argA
[0];
433 float4_array arg1
= argA
[1];
434 float4_array arg2
= argA
[2];
435 float4_array arg3
= argA
[3];
437 switch (combine
->ModeA
) {
439 for (i
= 0; i
< n
; i
++) {
440 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * scaleA
;
444 for (i
= 0; i
< n
; i
++) {
445 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * scaleA
;
449 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
450 /* (a * b) + (c * d) */
451 for (i
= 0; i
< n
; i
++) {
452 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
453 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
]) * scaleA
;
458 for (i
= 0; i
< n
; i
++) {
459 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * scaleA
;
464 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
465 /* (a * b) + (c * d) - 0.5 */
466 for (i
= 0; i
< n
; i
++) {
467 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
468 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
] -
474 for (i
= 0; i
< n
; i
++) {
475 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
480 for (i
= 0; i
< n
; i
++) {
481 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
482 arg1
[i
][ACOMP
] * (1.0F
- arg2
[i
][ACOMP
]))
487 for (i
= 0; i
< n
; i
++) {
488 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * scaleA
;
491 case GL_MODULATE_ADD_ATI
:
492 for (i
= 0; i
< n
; i
++) {
493 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
494 + arg1
[i
][ACOMP
]) * scaleA
;
497 case GL_MODULATE_SIGNED_ADD_ATI
:
498 for (i
= 0; i
< n
; i
++) {
499 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) +
500 arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
503 case GL_MODULATE_SUBTRACT_ATI
:
504 for (i
= 0; i
< n
; i
++) {
505 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
506 - arg1
[i
][ACOMP
]) * scaleA
;
510 _mesa_problem(ctx
, "invalid combine mode");
514 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
515 * This is kind of a kludge. It would have been better if the spec
516 * were written such that the GL_COMBINE_ALPHA value could be set to
519 if (combine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
520 combine
->ModeRGB
== GL_DOT3_RGBA
) {
521 for (i
= 0; i
< n
; i
++) {
522 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
526 for (i
= 0; i
< n
; i
++) {
527 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][RCOMP
], rgba
[i
][RCOMP
]);
528 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][GCOMP
], rgba
[i
][GCOMP
]);
529 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][BCOMP
], rgba
[i
][BCOMP
]);
530 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][ACOMP
], rgba
[i
][ACOMP
]);
536 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
537 * See GL_EXT_texture_swizzle.
540 swizzle_texels(GLuint swizzle
, GLuint count
, float4_array texels
)
542 const GLuint swzR
= GET_SWZ(swizzle
, 0);
543 const GLuint swzG
= GET_SWZ(swizzle
, 1);
544 const GLuint swzB
= GET_SWZ(swizzle
, 2);
545 const GLuint swzA
= GET_SWZ(swizzle
, 3);
549 vector
[SWIZZLE_ZERO
] = 0;
550 vector
[SWIZZLE_ONE
] = 1.0F
;
552 for (i
= 0; i
< count
; i
++) {
553 vector
[SWIZZLE_X
] = texels
[i
][0];
554 vector
[SWIZZLE_Y
] = texels
[i
][1];
555 vector
[SWIZZLE_Z
] = texels
[i
][2];
556 vector
[SWIZZLE_W
] = texels
[i
][3];
557 texels
[i
][RCOMP
] = vector
[swzR
];
558 texels
[i
][GCOMP
] = vector
[swzG
];
559 texels
[i
][BCOMP
] = vector
[swzB
];
560 texels
[i
][ACOMP
] = vector
[swzA
];
566 * Apply texture mapping to a span of fragments.
569 _swrast_texture_span( GLcontext
*ctx
, SWspan
*span
)
571 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
572 GLfloat primary_rgba
[MAX_WIDTH
][4];
575 ASSERT(span
->end
<= MAX_WIDTH
);
578 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
580 if (swrast
->_TextureCombinePrimary
) {
582 for (i
= 0; i
< span
->end
; i
++) {
583 primary_rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][RCOMP
]);
584 primary_rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][GCOMP
]);
585 primary_rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][BCOMP
]);
586 primary_rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][ACOMP
]);
590 /* First must sample all bump maps */
591 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
592 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
&&
593 ctx
->Texture
.Unit
[unit
]._CurrentCombine
->ModeRGB
== GL_BUMP_ENVMAP_ATI
) {
594 const GLfloat (*texcoords
)[4]
595 = (const GLfloat (*)[4])
596 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+ unit
];
597 GLfloat (*targetcoords
)[4]
599 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+
600 ctx
->Texture
.Unit
[unit
].BumpTarget
- GL_TEXTURE0
];
602 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
603 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
604 GLfloat
*lambda
= span
->array
->lambda
[unit
];
606 GLchan (*texels
)[4] = (GLchan (*)[4])
607 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
609 float4_array texels
= get_texel_array(swrast
->TexelBuffer
, unit
,
613 GLfloat rotMatrix00
= ctx
->Texture
.Unit
[unit
].RotMatrix
[0];
614 GLfloat rotMatrix01
= ctx
->Texture
.Unit
[unit
].RotMatrix
[1];
615 GLfloat rotMatrix10
= ctx
->Texture
.Unit
[unit
].RotMatrix
[2];
616 GLfloat rotMatrix11
= ctx
->Texture
.Unit
[unit
].RotMatrix
[3];
618 /* adjust texture lod (lambda) */
619 if (span
->arrayMask
& SPAN_LAMBDA
) {
620 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
621 /* apply LOD bias, but don't clamp yet */
622 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
623 -ctx
->Const
.MaxTextureLodBias
,
624 ctx
->Const
.MaxTextureLodBias
);
626 for (i
= 0; i
< span
->end
; i
++) {
631 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
632 /* apply LOD clamping to lambda */
633 const GLfloat min
= curObj
->MinLod
;
634 const GLfloat max
= curObj
->MaxLod
;
636 for (i
= 0; i
< span
->end
; i
++) {
637 GLfloat l
= lambda
[i
];
638 lambda
[i
] = CLAMP(l
, min
, max
);
643 /* Sample the texture (span->end = number of fragments) */
644 swrast
->TextureSample
[unit
]( ctx
, texUnit
->_Current
, span
->end
,
645 texcoords
, lambda
, texels
);
647 /* manipulate the span values of the bump target
648 not sure this can work correctly even ignoring
649 the problem that channel is unsigned */
650 for (i
= 0; i
< span
->end
; i
++) {
651 #if CHAN_TYPE == GL_FLOAT
652 targetcoords
[i
][0] += (texels
[i
][0] * rotMatrix00
+ texels
[i
][1] *
653 rotMatrix01
) / targetcoords
[i
][3];
654 targetcoords
[i
][1] += (texels
[i
][0] * rotMatrix10
+ texels
[i
][1] *
655 rotMatrix11
) / targetcoords
[i
][3];
657 targetcoords
[i
][0] += (CHAN_TO_FLOAT(texels
[i
][1]) * rotMatrix00
+
658 CHAN_TO_FLOAT(texels
[i
][1]) * rotMatrix01
) /
660 targetcoords
[i
][1] += (CHAN_TO_FLOAT(texels
[i
][0]) * rotMatrix10
+
661 CHAN_TO_FLOAT(texels
[i
][1]) * rotMatrix11
) /
669 * Must do all texture sampling before combining in order to
670 * accomodate GL_ARB_texture_env_crossbar.
672 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
673 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
&&
674 ctx
->Texture
.Unit
[unit
]._CurrentCombine
->ModeRGB
!= GL_BUMP_ENVMAP_ATI
) {
675 const GLfloat (*texcoords
)[4] = (const GLfloat (*)[4])
676 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+ unit
];
677 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
678 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
679 GLfloat
*lambda
= span
->array
->lambda
[unit
];
680 float4_array texels
=
681 get_texel_array(swrast
->TexelBuffer
, unit
, span
->end
);
683 /* adjust texture lod (lambda) */
684 if (span
->arrayMask
& SPAN_LAMBDA
) {
685 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
686 /* apply LOD bias, but don't clamp yet */
687 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
688 -ctx
->Const
.MaxTextureLodBias
,
689 ctx
->Const
.MaxTextureLodBias
);
691 for (i
= 0; i
< span
->end
; i
++) {
696 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
697 /* apply LOD clamping to lambda */
698 const GLfloat min
= curObj
->MinLod
;
699 const GLfloat max
= curObj
->MaxLod
;
701 for (i
= 0; i
< span
->end
; i
++) {
702 GLfloat l
= lambda
[i
];
703 lambda
[i
] = CLAMP(l
, min
, max
);
708 /* Sample the texture (span->end = number of fragments) */
709 swrast
->TextureSample
[unit
]( ctx
, texUnit
->_Current
, span
->end
,
710 texcoords
, lambda
, texels
);
712 /* GL_SGI_texture_color_table */
713 if (texUnit
->ColorTableEnabled
) {
714 _mesa_lookup_rgba_float(&texUnit
->ColorTable
, span
->end
, texels
);
717 /* GL_EXT_texture_swizzle */
718 if (curObj
->_Swizzle
!= SWIZZLE_NOOP
) {
719 swizzle_texels(curObj
->_Swizzle
, span
->end
, texels
);
725 * OK, now apply the texture (aka texture combine/blend).
726 * We modify the span->color.rgba values.
728 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
729 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
730 texture_combine( ctx
, unit
, span
->end
,