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 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
28 #include "main/glheader.h"
29 #include "main/context.h"
30 #include "main/colormac.h"
31 #include "main/imports.h"
32 #include "main/pixeltransfer.h"
33 #include "main/samplerobj.h"
34 #include "program/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(SWcontext
*swrast
, GLuint unit
)
54 return (float4_array
) (swrast
->TexelBuffer
+ unit
* SWRAST_MAX_WIDTH
* 4 * omp_get_num_threads() + (SWRAST_MAX_WIDTH
* 4 * omp_get_thread_num()));
56 return (float4_array
) (swrast
->TexelBuffer
+ unit
* SWRAST_MAX_WIDTH
* 4);
63 * Do texture application for:
64 * GL_EXT_texture_env_combine
65 * GL_ARB_texture_env_combine
66 * GL_EXT_texture_env_dot3
67 * GL_ARB_texture_env_dot3
68 * GL_ATI_texture_env_combine3
69 * GL_NV_texture_env_combine4
70 * conventional GL texture env modes
72 * \param ctx rendering context
73 * \param unit the texture combiner unit
74 * \param primary_rgba incoming fragment color array
75 * \param texelBuffer pointer to texel colors for all texture units
77 * \param span two fields are used in this function:
78 * span->end: number of fragments to process
79 * span->array->rgba: incoming/result fragment colors
82 texture_combine( struct gl_context
*ctx
, GLuint unit
,
83 const float4_array primary_rgba
,
84 const GLfloat
*texelBuffer
,
87 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
88 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
89 const struct gl_tex_env_combine_state
*combine
= textureUnit
->_CurrentCombine
;
90 float4_array argRGB
[MAX_COMBINER_TERMS
];
91 float4_array argA
[MAX_COMBINER_TERMS
];
92 const GLfloat scaleRGB
= (GLfloat
) (1 << combine
->ScaleShiftRGB
);
93 const GLfloat scaleA
= (GLfloat
) (1 << combine
->ScaleShiftA
);
94 const GLuint numArgsRGB
= combine
->_NumArgsRGB
;
95 const GLuint numArgsA
= combine
->_NumArgsA
;
96 float4_array ccolor
[4], rgba
;
99 GLchan (*rgbaChan
)[4] = span
->array
->rgba
;
101 /* alloc temp pixel buffers */
102 rgba
= malloc(4 * n
* sizeof(GLfloat
));
104 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
108 for (i
= 0; i
< numArgsRGB
|| i
< numArgsA
; i
++) {
109 ccolor
[i
] = malloc(4 * n
* sizeof(GLfloat
));
115 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
121 for (i
= 0; i
< n
; i
++) {
122 rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][RCOMP
]);
123 rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][GCOMP
]);
124 rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][BCOMP
]);
125 rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][ACOMP
]);
129 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
132 combine->SourceRGB[0],
134 combine->SourceRGB[1],
135 combine->SourceA[1]);
139 * Do operand setup for up to 4 operands. Loop over the terms.
141 for (term
= 0; term
< numArgsRGB
; term
++) {
142 const GLenum srcRGB
= combine
->SourceRGB
[term
];
143 const GLenum operandRGB
= combine
->OperandRGB
[term
];
147 argRGB
[term
] = get_texel_array(swrast
, unit
);
149 case GL_PRIMARY_COLOR
:
150 argRGB
[term
] = primary_rgba
;
157 float4_array c
= ccolor
[term
];
158 GLfloat red
= textureUnit
->EnvColor
[0];
159 GLfloat green
= textureUnit
->EnvColor
[1];
160 GLfloat blue
= textureUnit
->EnvColor
[2];
161 GLfloat alpha
= textureUnit
->EnvColor
[3];
162 for (i
= 0; i
< n
; i
++) {
163 ASSIGN_4V(c
[i
], red
, green
, blue
, alpha
);
165 argRGB
[term
] = ccolor
[term
];
168 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
172 float4_array c
= ccolor
[term
];
173 for (i
= 0; i
< n
; i
++) {
174 ASSIGN_4V(c
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
176 argRGB
[term
] = ccolor
[term
];
181 float4_array c
= ccolor
[term
];
182 for (i
= 0; i
< n
; i
++) {
183 ASSIGN_4V(c
[i
], 1.0F
, 1.0F
, 1.0F
, 1.0F
);
185 argRGB
[term
] = ccolor
[term
];
189 /* ARB_texture_env_crossbar source */
191 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
192 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
193 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
195 argRGB
[term
] = get_texel_array(swrast
, srcUnit
);
199 if (operandRGB
!= GL_SRC_COLOR
) {
200 float4_array src
= argRGB
[term
];
201 float4_array dst
= ccolor
[term
];
203 /* point to new arg[term] storage */
204 argRGB
[term
] = ccolor
[term
];
206 switch (operandRGB
) {
207 case GL_ONE_MINUS_SRC_COLOR
:
208 for (i
= 0; i
< n
; i
++) {
209 dst
[i
][RCOMP
] = 1.0F
- src
[i
][RCOMP
];
210 dst
[i
][GCOMP
] = 1.0F
- src
[i
][GCOMP
];
211 dst
[i
][BCOMP
] = 1.0F
- src
[i
][BCOMP
];
215 for (i
= 0; i
< n
; i
++) {
218 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
221 case GL_ONE_MINUS_SRC_ALPHA
:
222 for (i
= 0; i
< n
; i
++) {
225 dst
[i
][BCOMP
] = 1.0F
- src
[i
][ACOMP
];
229 _mesa_problem(ctx
, "Bad operandRGB");
235 * Set up the argA[term] pointers
237 for (term
= 0; term
< numArgsA
; term
++) {
238 const GLenum srcA
= combine
->SourceA
[term
];
239 const GLenum operandA
= combine
->OperandA
[term
];
243 argA
[term
] = get_texel_array(swrast
, unit
);
245 case GL_PRIMARY_COLOR
:
246 argA
[term
] = primary_rgba
;
253 float4_array c
= ccolor
[term
];
254 GLfloat alpha
= textureUnit
->EnvColor
[3];
255 for (i
= 0; i
< n
; i
++)
257 argA
[term
] = ccolor
[term
];
260 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
264 float4_array c
= ccolor
[term
];
265 for (i
= 0; i
< n
; i
++)
267 argA
[term
] = ccolor
[term
];
272 float4_array c
= ccolor
[term
];
273 for (i
= 0; i
< n
; i
++)
275 argA
[term
] = ccolor
[term
];
279 /* ARB_texture_env_crossbar source */
281 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
282 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
283 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
285 argA
[term
] = get_texel_array(swrast
, srcUnit
);
289 if (operandA
== GL_ONE_MINUS_SRC_ALPHA
) {
290 float4_array src
= argA
[term
];
291 float4_array dst
= ccolor
[term
];
292 argA
[term
] = ccolor
[term
];
293 for (i
= 0; i
< n
; i
++) {
294 dst
[i
][ACOMP
] = 1.0F
- src
[i
][ACOMP
];
299 /* RGB channel combine */
301 float4_array arg0
= argRGB
[0];
302 float4_array arg1
= argRGB
[1];
303 float4_array arg2
= argRGB
[2];
304 float4_array arg3
= argRGB
[3];
306 switch (combine
->ModeRGB
) {
308 for (i
= 0; i
< n
; i
++) {
309 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * scaleRGB
;
310 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * scaleRGB
;
311 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * scaleRGB
;
315 for (i
= 0; i
< n
; i
++) {
316 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * scaleRGB
;
317 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * scaleRGB
;
318 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * scaleRGB
;
322 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
323 /* (a * b) + (c * d) */
324 for (i
= 0; i
< n
; i
++) {
325 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
326 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
]) * scaleRGB
;
327 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
328 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
]) * scaleRGB
;
329 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
330 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
]) * scaleRGB
;
334 /* 2-term addition */
335 for (i
= 0; i
< n
; i
++) {
336 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * scaleRGB
;
337 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * scaleRGB
;
338 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * scaleRGB
;
343 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
344 /* (a * b) + (c * d) - 0.5 */
345 for (i
= 0; i
< n
; i
++) {
346 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
347 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
348 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
349 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
350 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
351 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
355 for (i
= 0; i
< n
; i
++) {
356 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
357 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
358 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
363 for (i
= 0; i
< n
; i
++) {
364 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
365 arg1
[i
][RCOMP
] * (1.0F
- arg2
[i
][RCOMP
])) * scaleRGB
;
366 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
367 arg1
[i
][GCOMP
] * (1.0F
- arg2
[i
][GCOMP
])) * scaleRGB
;
368 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
369 arg1
[i
][BCOMP
] * (1.0F
- arg2
[i
][BCOMP
])) * scaleRGB
;
373 for (i
= 0; i
< n
; i
++) {
374 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * scaleRGB
;
375 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * scaleRGB
;
376 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * scaleRGB
;
379 case GL_DOT3_RGB_EXT
:
380 case GL_DOT3_RGBA_EXT
:
381 /* Do not scale the result by 1 2 or 4 */
382 for (i
= 0; i
< n
; i
++) {
383 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
384 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
385 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
387 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
388 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
393 /* DO scale the result by 1 2 or 4 */
394 for (i
= 0; i
< n
; i
++) {
395 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
396 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
397 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
399 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
400 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
403 case GL_MODULATE_ADD_ATI
:
404 for (i
= 0; i
< n
; i
++) {
405 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
406 arg1
[i
][RCOMP
]) * scaleRGB
;
407 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
408 arg1
[i
][GCOMP
]) * scaleRGB
;
409 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
410 arg1
[i
][BCOMP
]) * scaleRGB
;
413 case GL_MODULATE_SIGNED_ADD_ATI
:
414 for (i
= 0; i
< n
; i
++) {
415 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
416 arg1
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
417 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
418 arg1
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
419 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
420 arg1
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
423 case GL_MODULATE_SUBTRACT_ATI
:
424 for (i
= 0; i
< n
; i
++) {
425 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) -
426 arg1
[i
][RCOMP
]) * scaleRGB
;
427 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) -
428 arg1
[i
][GCOMP
]) * scaleRGB
;
429 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) -
430 arg1
[i
][BCOMP
]) * scaleRGB
;
433 case GL_BUMP_ENVMAP_ATI
:
434 /* this produces a fixed rgba color, and the coord calc is done elsewhere */
435 for (i
= 0; i
< n
; i
++) {
436 /* rgba result is 0,0,0,1 */
437 rgba
[i
][RCOMP
] = 0.0;
438 rgba
[i
][GCOMP
] = 0.0;
439 rgba
[i
][BCOMP
] = 0.0;
440 rgba
[i
][ACOMP
] = 1.0;
442 goto end
; /* no alpha processing */
444 _mesa_problem(ctx
, "invalid combine mode");
448 /* Alpha channel combine */
450 float4_array arg0
= argA
[0];
451 float4_array arg1
= argA
[1];
452 float4_array arg2
= argA
[2];
453 float4_array arg3
= argA
[3];
455 switch (combine
->ModeA
) {
457 for (i
= 0; i
< n
; i
++) {
458 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * scaleA
;
462 for (i
= 0; i
< n
; i
++) {
463 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * scaleA
;
467 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
468 /* (a * b) + (c * d) */
469 for (i
= 0; i
< n
; i
++) {
470 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
471 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
]) * scaleA
;
476 for (i
= 0; i
< n
; i
++) {
477 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * scaleA
;
482 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
483 /* (a * b) + (c * d) - 0.5 */
484 for (i
= 0; i
< n
; i
++) {
485 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
486 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
] -
492 for (i
= 0; i
< n
; i
++) {
493 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
498 for (i
= 0; i
< n
; i
++) {
499 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
500 arg1
[i
][ACOMP
] * (1.0F
- arg2
[i
][ACOMP
]))
505 for (i
= 0; i
< n
; i
++) {
506 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * scaleA
;
509 case GL_MODULATE_ADD_ATI
:
510 for (i
= 0; i
< n
; i
++) {
511 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
512 + arg1
[i
][ACOMP
]) * scaleA
;
515 case GL_MODULATE_SIGNED_ADD_ATI
:
516 for (i
= 0; i
< n
; i
++) {
517 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) +
518 arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
521 case GL_MODULATE_SUBTRACT_ATI
:
522 for (i
= 0; i
< n
; i
++) {
523 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
524 - arg1
[i
][ACOMP
]) * scaleA
;
528 _mesa_problem(ctx
, "invalid combine mode");
532 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
533 * This is kind of a kludge. It would have been better if the spec
534 * were written such that the GL_COMBINE_ALPHA value could be set to
537 if (combine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
538 combine
->ModeRGB
== GL_DOT3_RGBA
) {
539 for (i
= 0; i
< n
; i
++) {
540 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
544 for (i
= 0; i
< n
; i
++) {
545 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][RCOMP
], rgba
[i
][RCOMP
]);
546 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][GCOMP
], rgba
[i
][GCOMP
]);
547 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][BCOMP
], rgba
[i
][BCOMP
]);
548 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][ACOMP
], rgba
[i
][ACOMP
]);
550 /* The span->array->rgba values are of CHAN type so set
551 * span->array->ChanType field accordingly.
553 span
->array
->ChanType
= CHAN_TYPE
;
556 for (i
= 0; i
< numArgsRGB
|| i
< numArgsA
; i
++) {
564 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
565 * See GL_EXT_texture_swizzle.
568 swizzle_texels(GLuint swizzle
, GLuint count
, float4_array texels
)
570 const GLuint swzR
= GET_SWZ(swizzle
, 0);
571 const GLuint swzG
= GET_SWZ(swizzle
, 1);
572 const GLuint swzB
= GET_SWZ(swizzle
, 2);
573 const GLuint swzA
= GET_SWZ(swizzle
, 3);
577 vector
[SWIZZLE_ZERO
] = 0;
578 vector
[SWIZZLE_ONE
] = 1.0F
;
580 for (i
= 0; i
< count
; i
++) {
581 vector
[SWIZZLE_X
] = texels
[i
][0];
582 vector
[SWIZZLE_Y
] = texels
[i
][1];
583 vector
[SWIZZLE_Z
] = texels
[i
][2];
584 vector
[SWIZZLE_W
] = texels
[i
][3];
585 texels
[i
][RCOMP
] = vector
[swzR
];
586 texels
[i
][GCOMP
] = vector
[swzG
];
587 texels
[i
][BCOMP
] = vector
[swzB
];
588 texels
[i
][ACOMP
] = vector
[swzA
];
594 * Apply texture mapping to a span of fragments.
597 _swrast_texture_span( struct gl_context
*ctx
, SWspan
*span
)
599 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
600 float4_array primary_rgba
;
603 if (!swrast
->TexelBuffer
) {
605 const GLint maxThreads
= omp_get_max_threads();
607 const GLint maxThreads
= 1;
610 /* TexelBuffer is also global and normally shared by all SWspan
611 * instances; when running with multiple threads, create one per
614 swrast
->TexelBuffer
=
615 malloc(ctx
->Const
.FragmentProgram
.MaxTextureImageUnits
* maxThreads
*
616 SWRAST_MAX_WIDTH
* 4 * sizeof(GLfloat
));
617 if (!swrast
->TexelBuffer
) {
618 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
623 primary_rgba
= malloc(span
->end
* 4 * sizeof(GLfloat
));
626 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_span");
630 ASSERT(span
->end
<= SWRAST_MAX_WIDTH
);
633 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
635 if (swrast
->_TextureCombinePrimary
) {
637 for (i
= 0; i
< span
->end
; i
++) {
638 primary_rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][RCOMP
]);
639 primary_rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][GCOMP
]);
640 primary_rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][BCOMP
]);
641 primary_rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][ACOMP
]);
645 /* First must sample all bump maps */
646 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
647 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
649 if (texUnit
->_ReallyEnabled
&&
650 texUnit
->_CurrentCombine
->ModeRGB
== GL_BUMP_ENVMAP_ATI
) {
651 const GLfloat (*texcoords
)[4] = (const GLfloat (*)[4])
652 span
->array
->attribs
[VARYING_SLOT_TEX0
+ unit
];
653 float4_array targetcoords
=
654 span
->array
->attribs
[VARYING_SLOT_TEX0
+
655 ctx
->Texture
.Unit
[unit
].BumpTarget
- GL_TEXTURE0
];
657 const struct gl_sampler_object
*samp
= _mesa_get_samplerobj(ctx
, unit
);
658 GLfloat
*lambda
= span
->array
->lambda
[unit
];
659 float4_array texels
= get_texel_array(swrast
, unit
);
661 GLfloat rotMatrix00
= ctx
->Texture
.Unit
[unit
].RotMatrix
[0];
662 GLfloat rotMatrix01
= ctx
->Texture
.Unit
[unit
].RotMatrix
[1];
663 GLfloat rotMatrix10
= ctx
->Texture
.Unit
[unit
].RotMatrix
[2];
664 GLfloat rotMatrix11
= ctx
->Texture
.Unit
[unit
].RotMatrix
[3];
666 /* adjust texture lod (lambda) */
667 if (span
->arrayMask
& SPAN_LAMBDA
) {
668 if (texUnit
->LodBias
+ samp
->LodBias
!= 0.0F
) {
669 /* apply LOD bias, but don't clamp yet */
670 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ samp
->LodBias
,
671 -ctx
->Const
.MaxTextureLodBias
,
672 ctx
->Const
.MaxTextureLodBias
);
674 for (i
= 0; i
< span
->end
; i
++) {
679 if (samp
->MinLod
!= -1000.0 ||
680 samp
->MaxLod
!= 1000.0) {
681 /* apply LOD clamping to lambda */
682 const GLfloat min
= samp
->MinLod
;
683 const GLfloat max
= samp
->MaxLod
;
685 for (i
= 0; i
< span
->end
; i
++) {
686 GLfloat l
= lambda
[i
];
687 lambda
[i
] = CLAMP(l
, min
, max
);
692 /* Sample the texture (span->end = number of fragments) */
693 swrast
->TextureSample
[unit
]( ctx
, samp
,
694 ctx
->Texture
.Unit
[unit
]._Current
,
695 span
->end
, texcoords
, lambda
, texels
);
697 /* manipulate the span values of the bump target
698 not sure this can work correctly even ignoring
699 the problem that channel is unsigned */
700 for (i
= 0; i
< span
->end
; i
++) {
701 targetcoords
[i
][0] += (texels
[i
][0] * rotMatrix00
+ texels
[i
][1] *
702 rotMatrix01
) / targetcoords
[i
][3];
703 targetcoords
[i
][1] += (texels
[i
][0] * rotMatrix10
+ texels
[i
][1] *
704 rotMatrix11
) / targetcoords
[i
][3];
710 * Must do all texture sampling before combining in order to
711 * accomodate GL_ARB_texture_env_crossbar.
713 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
714 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
715 if (texUnit
->_ReallyEnabled
&&
716 texUnit
->_CurrentCombine
->ModeRGB
!= GL_BUMP_ENVMAP_ATI
) {
717 const GLfloat (*texcoords
)[4] = (const GLfloat (*)[4])
718 span
->array
->attribs
[VARYING_SLOT_TEX0
+ unit
];
719 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
720 const struct gl_sampler_object
*samp
= _mesa_get_samplerobj(ctx
, unit
);
721 GLfloat
*lambda
= span
->array
->lambda
[unit
];
722 float4_array texels
= get_texel_array(swrast
, unit
);
724 /* adjust texture lod (lambda) */
725 if (span
->arrayMask
& SPAN_LAMBDA
) {
726 if (texUnit
->LodBias
+ samp
->LodBias
!= 0.0F
) {
727 /* apply LOD bias, but don't clamp yet */
728 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ samp
->LodBias
,
729 -ctx
->Const
.MaxTextureLodBias
,
730 ctx
->Const
.MaxTextureLodBias
);
732 for (i
= 0; i
< span
->end
; i
++) {
737 if (samp
->MinLod
!= -1000.0 ||
738 samp
->MaxLod
!= 1000.0) {
739 /* apply LOD clamping to lambda */
740 const GLfloat min
= samp
->MinLod
;
741 const GLfloat max
= samp
->MaxLod
;
743 for (i
= 0; i
< span
->end
; i
++) {
744 GLfloat l
= lambda
[i
];
745 lambda
[i
] = CLAMP(l
, min
, max
);
749 else if (samp
->MaxAnisotropy
> 1.0 &&
750 samp
->MinFilter
== GL_LINEAR_MIPMAP_LINEAR
) {
751 /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
752 * it requires the current SWspan *span as an additional parameter.
753 * In order to keep the same function signature, the unused lambda
754 * parameter will be modified to actually contain the SWspan pointer.
755 * This is a Hack. To make it right, the texture_sample_func
756 * signature and all implementing functions need to be modified.
758 /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
759 lambda
= (GLfloat
*)span
;
762 /* Sample the texture (span->end = number of fragments) */
763 swrast
->TextureSample
[unit
]( ctx
, samp
,
764 ctx
->Texture
.Unit
[unit
]._Current
,
765 span
->end
, texcoords
, lambda
, texels
);
767 /* GL_EXT_texture_swizzle */
768 if (curObj
->_Swizzle
!= SWIZZLE_NOOP
) {
769 swizzle_texels(curObj
->_Swizzle
, span
->end
, texels
);
775 * OK, now apply the texture (aka texture combine/blend).
776 * We modify the span->color.rgba values.
778 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
779 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
780 texture_combine(ctx
, unit
, primary_rgba
, swrast
->TexelBuffer
, span
);