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/macros.h"
33 #include "main/pixel.h"
34 #include "shader/prog_instruction.h"
36 #include "s_context.h"
37 #include "s_texcombine.h"
41 * Pointer to array of float[4]
42 * This type makes the code below more concise and avoids a lot of casting.
44 typedef float (*float4_array
)[4];
48 * Return array of texels for given unit.
50 static INLINE float4_array
51 get_texel_array(const GLfloat
*texelBuffer
, GLuint unit
, GLuint numTexels
)
54 (texelBuffer
+ unit
* numTexels
* 4 * sizeof(GLfloat
));
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
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
75 * \param rgba incoming/result fragment colors
78 texture_combine( const GLcontext
*ctx
, GLuint unit
, GLuint n
,
79 const float4_array primary_rgba
,
80 const GLfloat
*texelBuffer
,
81 GLchan (*rgbaChan
)[4] )
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];
95 ASSERT(CONST_SWRAST_CONTEXT(ctx
)->_AnyTextureCombine
);
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
]);
105 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
108 combine->SourceRGB[0],
110 combine->SourceRGB[1],
111 combine->SourceA[1]);
115 * Do operand setup for up to 4 operands. Loop over the terms.
117 for (term
= 0; term
< numArgsRGB
; term
++) {
118 const GLenum srcRGB
= combine
->SourceRGB
[term
];
119 const GLenum operandRGB
= combine
->OperandRGB
[term
];
123 argRGB
[term
] = get_texel_array(texelBuffer
, unit
, n
);
125 case GL_PRIMARY_COLOR
:
126 argRGB
[term
] = primary_rgba
;
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
);
141 argRGB
[term
] = ccolor
[term
];
144 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
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
);
152 argRGB
[term
] = ccolor
[term
];
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
);
161 argRGB
[term
] = ccolor
[term
];
165 /* ARB_texture_env_crossbar source */
167 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
168 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
169 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
171 argRGB
[term
] = get_texel_array(texelBuffer
, srcUnit
, n
);
175 if (operandRGB
!= GL_SRC_COLOR
) {
176 float4_array src
= argRGB
[term
];
177 float4_array dst
= ccolor
[term
];
179 /* point to new arg[term] storage */
180 argRGB
[term
] = ccolor
[term
];
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
];
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
];
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
];
205 _mesa_problem(ctx
, "Bad operandRGB");
211 * Set up the argA[term] pointers
213 for (term
= 0; term
< numArgsA
; term
++) {
214 const GLenum srcA
= combine
->SourceA
[term
];
215 const GLenum operandA
= combine
->OperandA
[term
];
219 argA
[term
] = get_texel_array(texelBuffer
, unit
, n
);
221 case GL_PRIMARY_COLOR
:
222 argA
[term
] = primary_rgba
;
229 float4_array c
= ccolor
[term
];
230 GLfloat alpha
= textureUnit
->EnvColor
[3];
231 for (i
= 0; i
< n
; i
++)
233 argA
[term
] = ccolor
[term
];
236 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
240 float4_array c
= ccolor
[term
];
241 for (i
= 0; i
< n
; i
++)
243 argA
[term
] = ccolor
[term
];
248 float4_array c
= ccolor
[term
];
249 for (i
= 0; i
< n
; i
++)
251 argA
[term
] = ccolor
[term
];
255 /* ARB_texture_env_crossbar source */
257 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
258 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
259 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
261 argA
[term
] = get_texel_array(texelBuffer
, srcUnit
, n
);
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
];
275 /* RGB channel combine */
277 float4_array arg0
= argRGB
[0];
278 float4_array arg1
= argRGB
[1];
279 float4_array arg2
= argRGB
[2];
280 float4_array arg3
= argRGB
[3];
282 switch (combine
->ModeRGB
) {
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
))
363 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
364 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLfloat
) dot
;
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
))
375 dot
= CLAMP(dot
, 0.0, 1.0F
);
376 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = (GLfloat
) dot
;
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
;
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
;
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
;
409 case GL_BUMP_ENVMAP_ATI
:
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;
423 rgba
[i
][ACOMP
] = CHAN_MAX
;
427 return; /* no alpha processing */
429 _mesa_problem(ctx
, "invalid combine mode");
433 /* Alpha channel combine */
435 float4_array arg0
= argA
[0];
436 float4_array arg1
= argA
[1];
437 float4_array arg2
= argA
[2];
438 float4_array arg3
= argA
[3];
440 switch (combine
->ModeA
) {
442 for (i
= 0; i
< n
; i
++) {
443 GLfloat a
= arg0
[i
][ACOMP
] * scaleA
;
444 rgba
[i
][ACOMP
] = (GLfloat
) MIN2(a
, 1.0F
);
448 for (i
= 0; i
< n
; i
++) {
449 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * scaleA
;
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
;
462 for (i
= 0; i
< n
; i
++) {
463 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * scaleA
;
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
] -
478 for (i
= 0; i
< n
; i
++) {
479 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
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
]))
491 for (i
= 0; i
< n
; i
++) {
492 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * scaleA
;
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
;
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
;
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
;
514 _mesa_problem(ctx
, "invalid combine mode");
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
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
];
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
]);
541 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
542 * See GL_EXT_texture_swizzle.
545 swizzle_texels(GLuint swizzle
, GLuint count
, float4_array texels
)
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);
554 vector
[SWIZZLE_ZERO
] = 0;
555 vector
[SWIZZLE_ONE
] = 1.0F
;
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
];
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.
582 texture_apply( const GLcontext
*ctx
,
583 const struct gl_texture_unit
*texUnit
,
585 float4_array primary_rgba
,
587 GLchan rgbaChan
[][4] )
591 GLfloat Rc
, Gc
, Bc
, Ac
;
593 GLfloat rgba
[MAX_WIDTH
][4];
598 ASSERT(texUnit
->_Current
);
600 baseLevel
= texUnit
->_Current
->BaseLevel
;
601 ASSERT(texUnit
->_Current
->Image
[0][baseLevel
]);
603 format
= texUnit
->_Current
->Image
[0][baseLevel
]->_BaseFormat
;
605 if (format
== GL_COLOR_INDEX
|| format
== GL_YCBCR_MESA
) {
606 format
= GL_RGBA
; /* a bit of a hack */
608 else if (format
== GL_DEPTH_COMPONENT
|| format
== GL_DEPTH_STENCIL_EXT
) {
609 format
= texUnit
->_Current
->DepthMode
;
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
]);
622 switch (texUnit
->EnvMode
) {
629 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
635 GLfloat Lt
= texel
[i
][RCOMP
];
636 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
640 case GL_LUMINANCE_ALPHA
:
642 GLfloat Lt
= texel
[i
][RCOMP
];
644 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = Lt
;
646 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
652 GLfloat It
= texel
[i
][RCOMP
];
653 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = It
;
661 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
662 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
663 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
670 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
671 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
672 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
674 rgba
[i
][ACOMP
] = texel
[i
][ACOMP
];
678 _mesa_problem(ctx
, "Bad format (GL_REPLACE) in texture_apply");
689 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * texel
[i
][ACOMP
];
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
;
702 case GL_LUMINANCE_ALPHA
:
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
;
710 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * texel
[i
][ACOMP
];
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
;
721 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * It
;
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
];
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
];
740 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * texel
[i
][ACOMP
];
744 _mesa_problem(ctx
, "Bad format (GL_MODULATE) in texture_apply");
753 case GL_LUMINANCE_ALPHA
:
760 rgba
[i
][RCOMP
] = texel
[i
][RCOMP
];
761 rgba
[i
][GCOMP
] = texel
[i
][GCOMP
];
762 rgba
[i
][BCOMP
] = texel
[i
][BCOMP
];
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
;
777 _mesa_problem(ctx
, "Bad format (GL_DECAL) in texture_apply");
783 Rc
= texUnit
->EnvColor
[0];
784 Gc
= texUnit
->EnvColor
[1];
785 Bc
= texUnit
->EnvColor
[2];
786 Ac
= texUnit
->EnvColor
[3];
792 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * texel
[i
][ACOMP
];
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
;
805 case GL_LUMINANCE_ALPHA
:
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
;
813 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * texel
[i
][ACOMP
];
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
;
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
];
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
];
849 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * texel
[i
][ACOMP
];
853 _mesa_problem(ctx
, "Bad format (GL_BLEND) in texture_apply");
858 case GL_ADD
: /* GL_EXT_texture_add_env */
865 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * texel
[i
][ACOMP
];
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
);
880 case GL_LUMINANCE_ALPHA
:
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
];
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
);
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
);
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
];
928 _mesa_problem(ctx
, "Bad format (GL_ADD) in texture_apply");
934 _mesa_problem(ctx
, "Bad env mode in texture_apply");
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
]);
950 * Apply texture mapping to a span of fragments.
953 _swrast_texture_span( GLcontext
*ctx
, SWspan
*span
)
955 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
956 GLfloat primary_rgba
[MAX_WIDTH
][4];
959 ASSERT(span
->end
<= MAX_WIDTH
);
962 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
964 if (swrast
->_AnyTextureCombine
) {
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
]);
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]
983 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+
984 ctx
->Texture
.Unit
[unit
].BumpTarget
- GL_TEXTURE0
];
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
];
990 GLchan (*texels
)[4] = (GLchan (*)[4])
991 (swrast
->TexelBuffer
+ unit
* (span
->end
* 4 * sizeof(GLchan
)));
993 float4_array texels
= get_texel_array(swrast
->TexelBuffer
, unit
,
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];
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
);
1010 for (i
= 0; i
< span
->end
; i
++) {
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
;
1020 for (i
= 0; i
< span
->end
; i
++) {
1021 GLfloat l
= lambda
[i
];
1022 lambda
[i
] = CLAMP(l
, min
, max
);
1027 /* Sample the texture (span->end = number of fragments) */
1028 swrast
->TextureSample
[unit
]( ctx
, texUnit
->_Current
, span
->end
,
1029 texcoords
, lambda
, texels
);
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];
1041 targetcoords
[i
][0] += (CHAN_TO_FLOAT(texels
[i
][1]) * rotMatrix00
+
1042 CHAN_TO_FLOAT(texels
[i
][1]) * rotMatrix01
) /
1044 targetcoords
[i
][1] += (CHAN_TO_FLOAT(texels
[i
][0]) * rotMatrix10
+
1045 CHAN_TO_FLOAT(texels
[i
][1]) * rotMatrix11
) /
1053 * Must do all texture sampling before combining in order to
1054 * accomodate GL_ARB_texture_env_crossbar.
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
);
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
);
1075 for (i
= 0; i
< span
->end
; i
++) {
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
;
1085 for (i
= 0; i
< span
->end
; i
++) {
1086 GLfloat l
= lambda
[i
];
1087 lambda
[i
] = CLAMP(l
, min
, max
);
1092 /* Sample the texture (span->end = number of fragments) */
1093 swrast
->TextureSample
[unit
]( ctx
, texUnit
->_Current
, span
->end
,
1094 texcoords
, lambda
, texels
);
1096 /* GL_SGI_texture_color_table */
1097 if (texUnit
->ColorTableEnabled
) {
1098 _mesa_lookup_rgba_float(&texUnit
->ColorTable
, span
->end
, texels
);
1101 /* GL_EXT_texture_swizzle */
1102 if (curObj
->_Swizzle
!= SWIZZLE_NOOP
) {
1103 swizzle_texels(curObj
->_Swizzle
, span
->end
, texels
);
1110 * OK, now apply the texture (aka texture combine/blend).
1111 * We modify the span->color.rgba values.
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
,
1119 swrast
->TexelBuffer
,
1120 span
->array
->rgba
);
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
);