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/imports.h"
31 #include "main/pixeltransfer.h"
32 #include "program/prog_instruction.h"
34 #include "s_context.h"
35 #include "s_texcombine.h"
39 * Pointer to array of float[4]
40 * This type makes the code below more concise and avoids a lot of casting.
42 typedef float (*float4_array
)[4];
46 * Return array of texels for given unit.
48 static INLINE float4_array
49 get_texel_array(SWcontext
*swrast
, GLuint unit
)
51 return (float4_array
) (swrast
->TexelBuffer
+ unit
* MAX_WIDTH
* 4);
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
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
72 * \param rgba incoming/result fragment colors
75 texture_combine( struct gl_context
*ctx
, GLuint unit
, GLuint n
,
76 const float4_array primary_rgba
,
77 const GLfloat
*texelBuffer
,
78 GLchan (*rgbaChan
)[4] )
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 float4_array ccolor
[4], rgba
;
92 /* alloc temp pixel buffers */
93 rgba
= (float4_array
) malloc(4 * n
* sizeof(GLfloat
));
95 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
99 for (i
= 0; i
< numArgsRGB
|| i
< numArgsA
; i
++) {
100 ccolor
[i
] = (float4_array
) malloc(4 * n
* sizeof(GLfloat
));
106 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
111 for (i
= 0; i
< n
; i
++) {
112 rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][RCOMP
]);
113 rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][GCOMP
]);
114 rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][BCOMP
]);
115 rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][ACOMP
]);
119 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
122 combine->SourceRGB[0],
124 combine->SourceRGB[1],
125 combine->SourceA[1]);
129 * Do operand setup for up to 4 operands. Loop over the terms.
131 for (term
= 0; term
< numArgsRGB
; term
++) {
132 const GLenum srcRGB
= combine
->SourceRGB
[term
];
133 const GLenum operandRGB
= combine
->OperandRGB
[term
];
137 argRGB
[term
] = get_texel_array(swrast
, unit
);
139 case GL_PRIMARY_COLOR
:
140 argRGB
[term
] = primary_rgba
;
147 float4_array c
= ccolor
[term
];
148 GLfloat red
= textureUnit
->EnvColor
[0];
149 GLfloat green
= textureUnit
->EnvColor
[1];
150 GLfloat blue
= textureUnit
->EnvColor
[2];
151 GLfloat alpha
= textureUnit
->EnvColor
[3];
152 for (i
= 0; i
< n
; i
++) {
153 ASSIGN_4V(c
[i
], red
, green
, blue
, alpha
);
155 argRGB
[term
] = ccolor
[term
];
158 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
162 float4_array c
= ccolor
[term
];
163 for (i
= 0; i
< n
; i
++) {
164 ASSIGN_4V(c
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
166 argRGB
[term
] = ccolor
[term
];
171 float4_array c
= ccolor
[term
];
172 for (i
= 0; i
< n
; i
++) {
173 ASSIGN_4V(c
[i
], 1.0F
, 1.0F
, 1.0F
, 1.0F
);
175 argRGB
[term
] = ccolor
[term
];
179 /* ARB_texture_env_crossbar source */
181 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
182 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
183 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
185 argRGB
[term
] = get_texel_array(swrast
, srcUnit
);
189 if (operandRGB
!= GL_SRC_COLOR
) {
190 float4_array src
= argRGB
[term
];
191 float4_array dst
= ccolor
[term
];
193 /* point to new arg[term] storage */
194 argRGB
[term
] = ccolor
[term
];
196 switch (operandRGB
) {
197 case GL_ONE_MINUS_SRC_COLOR
:
198 for (i
= 0; i
< n
; i
++) {
199 dst
[i
][RCOMP
] = 1.0F
- src
[i
][RCOMP
];
200 dst
[i
][GCOMP
] = 1.0F
- src
[i
][GCOMP
];
201 dst
[i
][BCOMP
] = 1.0F
- src
[i
][BCOMP
];
205 for (i
= 0; i
< n
; i
++) {
208 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
211 case GL_ONE_MINUS_SRC_ALPHA
:
212 for (i
= 0; i
< n
; i
++) {
215 dst
[i
][BCOMP
] = 1.0F
- src
[i
][ACOMP
];
219 _mesa_problem(ctx
, "Bad operandRGB");
225 * Set up the argA[term] pointers
227 for (term
= 0; term
< numArgsA
; term
++) {
228 const GLenum srcA
= combine
->SourceA
[term
];
229 const GLenum operandA
= combine
->OperandA
[term
];
233 argA
[term
] = get_texel_array(swrast
, unit
);
235 case GL_PRIMARY_COLOR
:
236 argA
[term
] = primary_rgba
;
243 float4_array c
= ccolor
[term
];
244 GLfloat alpha
= textureUnit
->EnvColor
[3];
245 for (i
= 0; i
< n
; i
++)
247 argA
[term
] = ccolor
[term
];
250 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
254 float4_array c
= ccolor
[term
];
255 for (i
= 0; i
< n
; i
++)
257 argA
[term
] = ccolor
[term
];
262 float4_array c
= ccolor
[term
];
263 for (i
= 0; i
< n
; i
++)
265 argA
[term
] = ccolor
[term
];
269 /* ARB_texture_env_crossbar source */
271 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
272 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
273 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
275 argA
[term
] = get_texel_array(swrast
, srcUnit
);
279 if (operandA
== GL_ONE_MINUS_SRC_ALPHA
) {
280 float4_array src
= argA
[term
];
281 float4_array dst
= ccolor
[term
];
282 argA
[term
] = ccolor
[term
];
283 for (i
= 0; i
< n
; i
++) {
284 dst
[i
][ACOMP
] = 1.0F
- src
[i
][ACOMP
];
289 /* RGB channel combine */
291 float4_array arg0
= argRGB
[0];
292 float4_array arg1
= argRGB
[1];
293 float4_array arg2
= argRGB
[2];
294 float4_array arg3
= argRGB
[3];
296 switch (combine
->ModeRGB
) {
298 for (i
= 0; i
< n
; i
++) {
299 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * scaleRGB
;
300 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * scaleRGB
;
301 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * scaleRGB
;
305 for (i
= 0; i
< n
; i
++) {
306 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * scaleRGB
;
307 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * scaleRGB
;
308 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * scaleRGB
;
312 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
313 /* (a * b) + (c * d) */
314 for (i
= 0; i
< n
; i
++) {
315 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
316 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
]) * scaleRGB
;
317 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
318 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
]) * scaleRGB
;
319 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
320 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
]) * scaleRGB
;
324 /* 2-term addition */
325 for (i
= 0; i
< n
; i
++) {
326 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * scaleRGB
;
327 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * scaleRGB
;
328 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * scaleRGB
;
333 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
334 /* (a * b) + (c * d) - 0.5 */
335 for (i
= 0; i
< n
; i
++) {
336 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
337 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
338 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
339 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
340 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
341 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
345 for (i
= 0; i
< n
; i
++) {
346 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
347 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
348 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
353 for (i
= 0; i
< n
; i
++) {
354 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
355 arg1
[i
][RCOMP
] * (1.0F
- arg2
[i
][RCOMP
])) * scaleRGB
;
356 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
357 arg1
[i
][GCOMP
] * (1.0F
- arg2
[i
][GCOMP
])) * scaleRGB
;
358 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
359 arg1
[i
][BCOMP
] * (1.0F
- arg2
[i
][BCOMP
])) * scaleRGB
;
363 for (i
= 0; i
< n
; i
++) {
364 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * scaleRGB
;
365 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * scaleRGB
;
366 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * scaleRGB
;
369 case GL_DOT3_RGB_EXT
:
370 case GL_DOT3_RGBA_EXT
:
371 /* Do not scale the result by 1 2 or 4 */
372 for (i
= 0; i
< n
; i
++) {
373 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
374 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
375 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
377 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
378 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
383 /* DO scale the result by 1 2 or 4 */
384 for (i
= 0; i
< n
; i
++) {
385 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
386 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
387 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
389 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
390 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
393 case GL_MODULATE_ADD_ATI
:
394 for (i
= 0; i
< n
; i
++) {
395 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
396 arg1
[i
][RCOMP
]) * scaleRGB
;
397 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
398 arg1
[i
][GCOMP
]) * scaleRGB
;
399 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
400 arg1
[i
][BCOMP
]) * scaleRGB
;
403 case GL_MODULATE_SIGNED_ADD_ATI
:
404 for (i
= 0; i
< n
; i
++) {
405 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
406 arg1
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
407 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
408 arg1
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
409 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
410 arg1
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
413 case GL_MODULATE_SUBTRACT_ATI
:
414 for (i
= 0; i
< n
; i
++) {
415 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) -
416 arg1
[i
][RCOMP
]) * scaleRGB
;
417 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) -
418 arg1
[i
][GCOMP
]) * scaleRGB
;
419 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) -
420 arg1
[i
][BCOMP
]) * scaleRGB
;
423 case GL_BUMP_ENVMAP_ATI
:
424 /* this produces a fixed rgba color, and the coord calc is done elsewhere */
425 for (i
= 0; i
< n
; i
++) {
426 /* rgba result is 0,0,0,1 */
427 rgba
[i
][RCOMP
] = 0.0;
428 rgba
[i
][GCOMP
] = 0.0;
429 rgba
[i
][BCOMP
] = 0.0;
430 rgba
[i
][ACOMP
] = 1.0;
432 goto end
; /* no alpha processing */
434 _mesa_problem(ctx
, "invalid combine mode");
438 /* Alpha channel combine */
440 float4_array arg0
= argA
[0];
441 float4_array arg1
= argA
[1];
442 float4_array arg2
= argA
[2];
443 float4_array arg3
= argA
[3];
445 switch (combine
->ModeA
) {
447 for (i
= 0; i
< n
; i
++) {
448 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * scaleA
;
452 for (i
= 0; i
< n
; i
++) {
453 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * scaleA
;
457 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
458 /* (a * b) + (c * d) */
459 for (i
= 0; i
< n
; i
++) {
460 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
461 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
]) * scaleA
;
466 for (i
= 0; i
< n
; i
++) {
467 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * scaleA
;
472 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
473 /* (a * b) + (c * d) - 0.5 */
474 for (i
= 0; i
< n
; i
++) {
475 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
476 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
] -
482 for (i
= 0; i
< n
; i
++) {
483 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
488 for (i
= 0; i
< n
; i
++) {
489 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
490 arg1
[i
][ACOMP
] * (1.0F
- arg2
[i
][ACOMP
]))
495 for (i
= 0; i
< n
; i
++) {
496 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * scaleA
;
499 case GL_MODULATE_ADD_ATI
:
500 for (i
= 0; i
< n
; i
++) {
501 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
502 + arg1
[i
][ACOMP
]) * scaleA
;
505 case GL_MODULATE_SIGNED_ADD_ATI
:
506 for (i
= 0; i
< n
; i
++) {
507 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) +
508 arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
511 case GL_MODULATE_SUBTRACT_ATI
:
512 for (i
= 0; i
< n
; i
++) {
513 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
514 - arg1
[i
][ACOMP
]) * scaleA
;
518 _mesa_problem(ctx
, "invalid combine mode");
522 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
523 * This is kind of a kludge. It would have been better if the spec
524 * were written such that the GL_COMBINE_ALPHA value could be set to
527 if (combine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
528 combine
->ModeRGB
== GL_DOT3_RGBA
) {
529 for (i
= 0; i
< n
; i
++) {
530 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
534 for (i
= 0; i
< n
; i
++) {
535 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][RCOMP
], rgba
[i
][RCOMP
]);
536 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][GCOMP
], rgba
[i
][GCOMP
]);
537 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][BCOMP
], rgba
[i
][BCOMP
]);
538 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][ACOMP
], rgba
[i
][ACOMP
]);
542 for (i
= 0; i
< numArgsRGB
|| i
< numArgsA
; i
++) {
550 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
551 * See GL_EXT_texture_swizzle.
554 swizzle_texels(GLuint swizzle
, GLuint count
, float4_array texels
)
556 const GLuint swzR
= GET_SWZ(swizzle
, 0);
557 const GLuint swzG
= GET_SWZ(swizzle
, 1);
558 const GLuint swzB
= GET_SWZ(swizzle
, 2);
559 const GLuint swzA
= GET_SWZ(swizzle
, 3);
563 vector
[SWIZZLE_ZERO
] = 0;
564 vector
[SWIZZLE_ONE
] = 1.0F
;
566 for (i
= 0; i
< count
; i
++) {
567 vector
[SWIZZLE_X
] = texels
[i
][0];
568 vector
[SWIZZLE_Y
] = texels
[i
][1];
569 vector
[SWIZZLE_Z
] = texels
[i
][2];
570 vector
[SWIZZLE_W
] = texels
[i
][3];
571 texels
[i
][RCOMP
] = vector
[swzR
];
572 texels
[i
][GCOMP
] = vector
[swzG
];
573 texels
[i
][BCOMP
] = vector
[swzB
];
574 texels
[i
][ACOMP
] = vector
[swzA
];
580 * Apply texture mapping to a span of fragments.
583 _swrast_texture_span( struct gl_context
*ctx
, SWspan
*span
)
585 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
586 float4_array primary_rgba
;
589 primary_rgba
= (float4_array
) malloc(span
->end
* 4 * sizeof(GLfloat
));
592 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_span");
596 ASSERT(span
->end
<= MAX_WIDTH
);
599 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
601 if (swrast
->_TextureCombinePrimary
) {
603 for (i
= 0; i
< span
->end
; i
++) {
604 primary_rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][RCOMP
]);
605 primary_rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][GCOMP
]);
606 primary_rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][BCOMP
]);
607 primary_rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][ACOMP
]);
611 /* First must sample all bump maps */
612 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
613 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
615 if (texUnit
->_ReallyEnabled
&&
616 texUnit
->_CurrentCombine
->ModeRGB
== GL_BUMP_ENVMAP_ATI
) {
617 const GLfloat (*texcoords
)[4] = (const GLfloat (*)[4])
618 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+ unit
];
619 float4_array targetcoords
=
620 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+
621 ctx
->Texture
.Unit
[unit
].BumpTarget
- GL_TEXTURE0
];
623 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
624 GLfloat
*lambda
= span
->array
->lambda
[unit
];
625 float4_array texels
= get_texel_array(swrast
, unit
);
627 GLfloat rotMatrix00
= ctx
->Texture
.Unit
[unit
].RotMatrix
[0];
628 GLfloat rotMatrix01
= ctx
->Texture
.Unit
[unit
].RotMatrix
[1];
629 GLfloat rotMatrix10
= ctx
->Texture
.Unit
[unit
].RotMatrix
[2];
630 GLfloat rotMatrix11
= ctx
->Texture
.Unit
[unit
].RotMatrix
[3];
632 /* adjust texture lod (lambda) */
633 if (span
->arrayMask
& SPAN_LAMBDA
) {
634 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
635 /* apply LOD bias, but don't clamp yet */
636 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
637 -ctx
->Const
.MaxTextureLodBias
,
638 ctx
->Const
.MaxTextureLodBias
);
640 for (i
= 0; i
< span
->end
; i
++) {
645 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
646 /* apply LOD clamping to lambda */
647 const GLfloat min
= curObj
->MinLod
;
648 const GLfloat max
= curObj
->MaxLod
;
650 for (i
= 0; i
< span
->end
; i
++) {
651 GLfloat l
= lambda
[i
];
652 lambda
[i
] = CLAMP(l
, min
, max
);
657 /* Sample the texture (span->end = number of fragments) */
658 swrast
->TextureSample
[unit
]( ctx
, texUnit
->_Current
, span
->end
,
659 texcoords
, lambda
, texels
);
661 /* manipulate the span values of the bump target
662 not sure this can work correctly even ignoring
663 the problem that channel is unsigned */
664 for (i
= 0; i
< span
->end
; i
++) {
665 targetcoords
[i
][0] += (texels
[i
][0] * rotMatrix00
+ texels
[i
][1] *
666 rotMatrix01
) / targetcoords
[i
][3];
667 targetcoords
[i
][1] += (texels
[i
][0] * rotMatrix10
+ texels
[i
][1] *
668 rotMatrix11
) / targetcoords
[i
][3];
674 * Must do all texture sampling before combining in order to
675 * accomodate GL_ARB_texture_env_crossbar.
677 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
678 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
679 if (texUnit
->_ReallyEnabled
&&
680 texUnit
->_CurrentCombine
->ModeRGB
!= GL_BUMP_ENVMAP_ATI
) {
681 const GLfloat (*texcoords
)[4] = (const GLfloat (*)[4])
682 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+ unit
];
683 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
684 GLfloat
*lambda
= span
->array
->lambda
[unit
];
685 float4_array texels
= get_texel_array(swrast
, unit
);
687 /* adjust texture lod (lambda) */
688 if (span
->arrayMask
& SPAN_LAMBDA
) {
689 if (texUnit
->LodBias
+ curObj
->LodBias
!= 0.0F
) {
690 /* apply LOD bias, but don't clamp yet */
691 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->LodBias
,
692 -ctx
->Const
.MaxTextureLodBias
,
693 ctx
->Const
.MaxTextureLodBias
);
695 for (i
= 0; i
< span
->end
; i
++) {
700 if (curObj
->MinLod
!= -1000.0 || curObj
->MaxLod
!= 1000.0) {
701 /* apply LOD clamping to lambda */
702 const GLfloat min
= curObj
->MinLod
;
703 const GLfloat max
= curObj
->MaxLod
;
705 for (i
= 0; i
< span
->end
; i
++) {
706 GLfloat l
= lambda
[i
];
707 lambda
[i
] = CLAMP(l
, min
, max
);
712 /* Sample the texture (span->end = number of fragments) */
713 swrast
->TextureSample
[unit
]( ctx
, texUnit
->_Current
, span
->end
,
714 texcoords
, lambda
, texels
);
716 /* GL_SGI_texture_color_table */
717 if (texUnit
->ColorTableEnabled
) {
718 _mesa_lookup_rgba_float(&texUnit
->ColorTable
, span
->end
, texels
);
721 /* GL_EXT_texture_swizzle */
722 if (curObj
->_Swizzle
!= SWIZZLE_NOOP
) {
723 swizzle_texels(curObj
->_Swizzle
, span
->end
, texels
);
729 * OK, now apply the texture (aka texture combine/blend).
730 * We modify the span->color.rgba values.
732 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
733 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
734 texture_combine( ctx
, unit
, span
->end
,