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
)
52 return (float4_array
) (swrast
->TexelBuffer
+ unit
* SWRAST_MAX_WIDTH
* 4 * omp_get_num_threads() + (SWRAST_MAX_WIDTH
* 4 * omp_get_thread_num()));
54 return (float4_array
) (swrast
->TexelBuffer
+ unit
* SWRAST_MAX_WIDTH
* 4);
61 * Do texture application for:
62 * GL_EXT_texture_env_combine
63 * GL_ARB_texture_env_combine
64 * GL_EXT_texture_env_dot3
65 * GL_ARB_texture_env_dot3
66 * GL_ATI_texture_env_combine3
67 * GL_NV_texture_env_combine4
68 * conventional GL texture env modes
70 * \param ctx rendering context
71 * \param unit the texture combiner unit
72 * \param primary_rgba incoming fragment color array
73 * \param texelBuffer pointer to texel colors for all texture units
75 * \param span two fields are used in this function:
76 * span->end: number of fragments to process
77 * span->array->rgba: incoming/result fragment colors
80 texture_combine( struct gl_context
*ctx
, GLuint unit
,
81 const float4_array primary_rgba
,
82 const GLfloat
*texelBuffer
,
85 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
86 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
87 const struct gl_tex_env_combine_state
*combine
= textureUnit
->_CurrentCombine
;
88 float4_array argRGB
[MAX_COMBINER_TERMS
];
89 float4_array argA
[MAX_COMBINER_TERMS
];
90 const GLfloat scaleRGB
= (GLfloat
) (1 << combine
->ScaleShiftRGB
);
91 const GLfloat scaleA
= (GLfloat
) (1 << combine
->ScaleShiftA
);
92 const GLuint numArgsRGB
= combine
->_NumArgsRGB
;
93 const GLuint numArgsA
= combine
->_NumArgsA
;
94 float4_array ccolor
[4], rgba
;
97 GLchan (*rgbaChan
)[4] = span
->array
->rgba
;
99 /* alloc temp pixel buffers */
100 rgba
= (float4_array
) malloc(4 * n
* sizeof(GLfloat
));
102 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
106 for (i
= 0; i
< numArgsRGB
|| i
< numArgsA
; i
++) {
107 ccolor
[i
] = (float4_array
) malloc(4 * n
* sizeof(GLfloat
));
113 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
119 for (i
= 0; i
< n
; i
++) {
120 rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][RCOMP
]);
121 rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][GCOMP
]);
122 rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][BCOMP
]);
123 rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][ACOMP
]);
127 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
130 combine->SourceRGB[0],
132 combine->SourceRGB[1],
133 combine->SourceA[1]);
137 * Do operand setup for up to 4 operands. Loop over the terms.
139 for (term
= 0; term
< numArgsRGB
; term
++) {
140 const GLenum srcRGB
= combine
->SourceRGB
[term
];
141 const GLenum operandRGB
= combine
->OperandRGB
[term
];
145 argRGB
[term
] = get_texel_array(swrast
, unit
);
147 case GL_PRIMARY_COLOR
:
148 argRGB
[term
] = primary_rgba
;
155 float4_array c
= ccolor
[term
];
156 GLfloat red
= textureUnit
->EnvColor
[0];
157 GLfloat green
= textureUnit
->EnvColor
[1];
158 GLfloat blue
= textureUnit
->EnvColor
[2];
159 GLfloat alpha
= textureUnit
->EnvColor
[3];
160 for (i
= 0; i
< n
; i
++) {
161 ASSIGN_4V(c
[i
], red
, green
, blue
, alpha
);
163 argRGB
[term
] = ccolor
[term
];
166 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
170 float4_array c
= ccolor
[term
];
171 for (i
= 0; i
< n
; i
++) {
172 ASSIGN_4V(c
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
174 argRGB
[term
] = ccolor
[term
];
179 float4_array c
= ccolor
[term
];
180 for (i
= 0; i
< n
; i
++) {
181 ASSIGN_4V(c
[i
], 1.0F
, 1.0F
, 1.0F
, 1.0F
);
183 argRGB
[term
] = ccolor
[term
];
187 /* ARB_texture_env_crossbar source */
189 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
190 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
191 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
193 argRGB
[term
] = get_texel_array(swrast
, srcUnit
);
197 if (operandRGB
!= GL_SRC_COLOR
) {
198 float4_array src
= argRGB
[term
];
199 float4_array dst
= ccolor
[term
];
201 /* point to new arg[term] storage */
202 argRGB
[term
] = ccolor
[term
];
204 switch (operandRGB
) {
205 case GL_ONE_MINUS_SRC_COLOR
:
206 for (i
= 0; i
< n
; i
++) {
207 dst
[i
][RCOMP
] = 1.0F
- src
[i
][RCOMP
];
208 dst
[i
][GCOMP
] = 1.0F
- src
[i
][GCOMP
];
209 dst
[i
][BCOMP
] = 1.0F
- src
[i
][BCOMP
];
213 for (i
= 0; i
< n
; i
++) {
216 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
219 case GL_ONE_MINUS_SRC_ALPHA
:
220 for (i
= 0; i
< n
; i
++) {
223 dst
[i
][BCOMP
] = 1.0F
- src
[i
][ACOMP
];
227 _mesa_problem(ctx
, "Bad operandRGB");
233 * Set up the argA[term] pointers
235 for (term
= 0; term
< numArgsA
; term
++) {
236 const GLenum srcA
= combine
->SourceA
[term
];
237 const GLenum operandA
= combine
->OperandA
[term
];
241 argA
[term
] = get_texel_array(swrast
, unit
);
243 case GL_PRIMARY_COLOR
:
244 argA
[term
] = primary_rgba
;
251 float4_array c
= ccolor
[term
];
252 GLfloat alpha
= textureUnit
->EnvColor
[3];
253 for (i
= 0; i
< n
; i
++)
255 argA
[term
] = ccolor
[term
];
258 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
262 float4_array c
= ccolor
[term
];
263 for (i
= 0; i
< n
; i
++)
265 argA
[term
] = ccolor
[term
];
270 float4_array c
= ccolor
[term
];
271 for (i
= 0; i
< n
; i
++)
273 argA
[term
] = ccolor
[term
];
277 /* ARB_texture_env_crossbar source */
279 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
280 ASSERT(srcUnit
< ctx
->Const
.MaxTextureUnits
);
281 if (!ctx
->Texture
.Unit
[srcUnit
]._ReallyEnabled
)
283 argA
[term
] = get_texel_array(swrast
, srcUnit
);
287 if (operandA
== GL_ONE_MINUS_SRC_ALPHA
) {
288 float4_array src
= argA
[term
];
289 float4_array dst
= ccolor
[term
];
290 argA
[term
] = ccolor
[term
];
291 for (i
= 0; i
< n
; i
++) {
292 dst
[i
][ACOMP
] = 1.0F
- src
[i
][ACOMP
];
297 /* RGB channel combine */
299 float4_array arg0
= argRGB
[0];
300 float4_array arg1
= argRGB
[1];
301 float4_array arg2
= argRGB
[2];
302 float4_array arg3
= argRGB
[3];
304 switch (combine
->ModeRGB
) {
306 for (i
= 0; i
< n
; i
++) {
307 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * scaleRGB
;
308 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * scaleRGB
;
309 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * scaleRGB
;
313 for (i
= 0; i
< n
; i
++) {
314 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * scaleRGB
;
315 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * scaleRGB
;
316 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * scaleRGB
;
320 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
321 /* (a * b) + (c * d) */
322 for (i
= 0; i
< n
; i
++) {
323 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
324 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
]) * scaleRGB
;
325 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
326 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
]) * scaleRGB
;
327 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
328 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
]) * scaleRGB
;
332 /* 2-term addition */
333 for (i
= 0; i
< n
; i
++) {
334 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * scaleRGB
;
335 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * scaleRGB
;
336 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * scaleRGB
;
341 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
342 /* (a * b) + (c * d) - 0.5 */
343 for (i
= 0; i
< n
; i
++) {
344 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
345 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
346 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
347 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
348 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
349 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
353 for (i
= 0; i
< n
; i
++) {
354 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
355 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
356 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
361 for (i
= 0; i
< n
; i
++) {
362 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
363 arg1
[i
][RCOMP
] * (1.0F
- arg2
[i
][RCOMP
])) * scaleRGB
;
364 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
365 arg1
[i
][GCOMP
] * (1.0F
- arg2
[i
][GCOMP
])) * scaleRGB
;
366 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
367 arg1
[i
][BCOMP
] * (1.0F
- arg2
[i
][BCOMP
])) * scaleRGB
;
371 for (i
= 0; i
< n
; i
++) {
372 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * scaleRGB
;
373 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * scaleRGB
;
374 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * scaleRGB
;
377 case GL_DOT3_RGB_EXT
:
378 case GL_DOT3_RGBA_EXT
:
379 /* Do not scale the result by 1 2 or 4 */
380 for (i
= 0; i
< n
; i
++) {
381 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
382 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
383 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
385 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
386 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
391 /* DO scale the result by 1 2 or 4 */
392 for (i
= 0; i
< n
; i
++) {
393 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
394 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
395 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
397 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
398 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
401 case GL_MODULATE_ADD_ATI
:
402 for (i
= 0; i
< n
; i
++) {
403 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
404 arg1
[i
][RCOMP
]) * scaleRGB
;
405 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
406 arg1
[i
][GCOMP
]) * scaleRGB
;
407 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
408 arg1
[i
][BCOMP
]) * scaleRGB
;
411 case GL_MODULATE_SIGNED_ADD_ATI
:
412 for (i
= 0; i
< n
; i
++) {
413 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
414 arg1
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
415 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
416 arg1
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
417 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
418 arg1
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
421 case GL_MODULATE_SUBTRACT_ATI
:
422 for (i
= 0; i
< n
; i
++) {
423 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) -
424 arg1
[i
][RCOMP
]) * scaleRGB
;
425 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) -
426 arg1
[i
][GCOMP
]) * scaleRGB
;
427 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) -
428 arg1
[i
][BCOMP
]) * scaleRGB
;
431 case GL_BUMP_ENVMAP_ATI
:
432 /* this produces a fixed rgba color, and the coord calc is done elsewhere */
433 for (i
= 0; i
< n
; i
++) {
434 /* rgba result is 0,0,0,1 */
435 rgba
[i
][RCOMP
] = 0.0;
436 rgba
[i
][GCOMP
] = 0.0;
437 rgba
[i
][BCOMP
] = 0.0;
438 rgba
[i
][ACOMP
] = 1.0;
440 goto end
; /* no alpha processing */
442 _mesa_problem(ctx
, "invalid combine mode");
446 /* Alpha channel combine */
448 float4_array arg0
= argA
[0];
449 float4_array arg1
= argA
[1];
450 float4_array arg2
= argA
[2];
451 float4_array arg3
= argA
[3];
453 switch (combine
->ModeA
) {
455 for (i
= 0; i
< n
; i
++) {
456 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * scaleA
;
460 for (i
= 0; i
< n
; i
++) {
461 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * scaleA
;
465 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
466 /* (a * b) + (c * d) */
467 for (i
= 0; i
< n
; i
++) {
468 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
469 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
]) * scaleA
;
474 for (i
= 0; i
< n
; i
++) {
475 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * scaleA
;
480 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
481 /* (a * b) + (c * d) - 0.5 */
482 for (i
= 0; i
< n
; i
++) {
483 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
484 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
] -
490 for (i
= 0; i
< n
; i
++) {
491 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
496 for (i
= 0; i
< n
; i
++) {
497 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
498 arg1
[i
][ACOMP
] * (1.0F
- arg2
[i
][ACOMP
]))
503 for (i
= 0; i
< n
; i
++) {
504 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * scaleA
;
507 case GL_MODULATE_ADD_ATI
:
508 for (i
= 0; i
< n
; i
++) {
509 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
510 + arg1
[i
][ACOMP
]) * scaleA
;
513 case GL_MODULATE_SIGNED_ADD_ATI
:
514 for (i
= 0; i
< n
; i
++) {
515 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) +
516 arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
519 case GL_MODULATE_SUBTRACT_ATI
:
520 for (i
= 0; i
< n
; i
++) {
521 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
522 - arg1
[i
][ACOMP
]) * scaleA
;
526 _mesa_problem(ctx
, "invalid combine mode");
530 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
531 * This is kind of a kludge. It would have been better if the spec
532 * were written such that the GL_COMBINE_ALPHA value could be set to
535 if (combine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
536 combine
->ModeRGB
== GL_DOT3_RGBA
) {
537 for (i
= 0; i
< n
; i
++) {
538 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
542 for (i
= 0; i
< n
; i
++) {
543 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][RCOMP
], rgba
[i
][RCOMP
]);
544 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][GCOMP
], rgba
[i
][GCOMP
]);
545 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][BCOMP
], rgba
[i
][BCOMP
]);
546 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][ACOMP
], rgba
[i
][ACOMP
]);
548 /* The span->array->rgba values are of CHAN type so set
549 * span->array->ChanType field accordingly.
551 span
->array
->ChanType
= CHAN_TYPE
;
554 for (i
= 0; i
< numArgsRGB
|| i
< numArgsA
; i
++) {
562 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
563 * See GL_EXT_texture_swizzle.
566 swizzle_texels(GLuint swizzle
, GLuint count
, float4_array texels
)
568 const GLuint swzR
= GET_SWZ(swizzle
, 0);
569 const GLuint swzG
= GET_SWZ(swizzle
, 1);
570 const GLuint swzB
= GET_SWZ(swizzle
, 2);
571 const GLuint swzA
= GET_SWZ(swizzle
, 3);
575 vector
[SWIZZLE_ZERO
] = 0;
576 vector
[SWIZZLE_ONE
] = 1.0F
;
578 for (i
= 0; i
< count
; i
++) {
579 vector
[SWIZZLE_X
] = texels
[i
][0];
580 vector
[SWIZZLE_Y
] = texels
[i
][1];
581 vector
[SWIZZLE_Z
] = texels
[i
][2];
582 vector
[SWIZZLE_W
] = texels
[i
][3];
583 texels
[i
][RCOMP
] = vector
[swzR
];
584 texels
[i
][GCOMP
] = vector
[swzG
];
585 texels
[i
][BCOMP
] = vector
[swzB
];
586 texels
[i
][ACOMP
] = vector
[swzA
];
592 * Apply texture mapping to a span of fragments.
595 _swrast_texture_span( struct gl_context
*ctx
, SWspan
*span
)
597 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
598 float4_array primary_rgba
;
601 if (!swrast
->TexelBuffer
) {
603 const GLint maxThreads
= omp_get_max_threads();
605 const GLint maxThreads
= 1;
608 /* TexelBuffer is also global and normally shared by all SWspan
609 * instances; when running with multiple threads, create one per
612 swrast
->TexelBuffer
=
613 (GLfloat
*) MALLOC(ctx
->Const
.MaxTextureImageUnits
* maxThreads
*
614 SWRAST_MAX_WIDTH
* 4 * sizeof(GLfloat
));
615 if (!swrast
->TexelBuffer
) {
616 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
621 primary_rgba
= (float4_array
) malloc(span
->end
* 4 * sizeof(GLfloat
));
624 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_span");
628 ASSERT(span
->end
<= SWRAST_MAX_WIDTH
);
631 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
633 if (swrast
->_TextureCombinePrimary
) {
635 for (i
= 0; i
< span
->end
; i
++) {
636 primary_rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][RCOMP
]);
637 primary_rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][GCOMP
]);
638 primary_rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][BCOMP
]);
639 primary_rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][ACOMP
]);
643 /* First must sample all bump maps */
644 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
645 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
647 if (texUnit
->_ReallyEnabled
&&
648 texUnit
->_CurrentCombine
->ModeRGB
== GL_BUMP_ENVMAP_ATI
) {
649 const GLfloat (*texcoords
)[4] = (const GLfloat (*)[4])
650 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+ unit
];
651 float4_array targetcoords
=
652 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+
653 ctx
->Texture
.Unit
[unit
].BumpTarget
- GL_TEXTURE0
];
655 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
656 GLfloat
*lambda
= span
->array
->lambda
[unit
];
657 float4_array texels
= get_texel_array(swrast
, unit
);
659 GLfloat rotMatrix00
= ctx
->Texture
.Unit
[unit
].RotMatrix
[0];
660 GLfloat rotMatrix01
= ctx
->Texture
.Unit
[unit
].RotMatrix
[1];
661 GLfloat rotMatrix10
= ctx
->Texture
.Unit
[unit
].RotMatrix
[2];
662 GLfloat rotMatrix11
= ctx
->Texture
.Unit
[unit
].RotMatrix
[3];
664 /* adjust texture lod (lambda) */
665 if (span
->arrayMask
& SPAN_LAMBDA
) {
666 if (texUnit
->LodBias
+ curObj
->Sampler
.LodBias
!= 0.0F
) {
667 /* apply LOD bias, but don't clamp yet */
668 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->Sampler
.LodBias
,
669 -ctx
->Const
.MaxTextureLodBias
,
670 ctx
->Const
.MaxTextureLodBias
);
672 for (i
= 0; i
< span
->end
; i
++) {
677 if (curObj
->Sampler
.MinLod
!= -1000.0 ||
678 curObj
->Sampler
.MaxLod
!= 1000.0) {
679 /* apply LOD clamping to lambda */
680 const GLfloat min
= curObj
->Sampler
.MinLod
;
681 const GLfloat max
= curObj
->Sampler
.MaxLod
;
683 for (i
= 0; i
< span
->end
; i
++) {
684 GLfloat l
= lambda
[i
];
685 lambda
[i
] = CLAMP(l
, min
, max
);
690 /* Sample the texture (span->end = number of fragments) */
691 swrast
->TextureSample
[unit
]( ctx
, texUnit
->_Current
, span
->end
,
692 texcoords
, lambda
, texels
);
694 /* manipulate the span values of the bump target
695 not sure this can work correctly even ignoring
696 the problem that channel is unsigned */
697 for (i
= 0; i
< span
->end
; i
++) {
698 targetcoords
[i
][0] += (texels
[i
][0] * rotMatrix00
+ texels
[i
][1] *
699 rotMatrix01
) / targetcoords
[i
][3];
700 targetcoords
[i
][1] += (texels
[i
][0] * rotMatrix10
+ texels
[i
][1] *
701 rotMatrix11
) / targetcoords
[i
][3];
707 * Must do all texture sampling before combining in order to
708 * accomodate GL_ARB_texture_env_crossbar.
710 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
711 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
712 if (texUnit
->_ReallyEnabled
&&
713 texUnit
->_CurrentCombine
->ModeRGB
!= GL_BUMP_ENVMAP_ATI
) {
714 const GLfloat (*texcoords
)[4] = (const GLfloat (*)[4])
715 span
->array
->attribs
[FRAG_ATTRIB_TEX0
+ unit
];
716 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
717 GLfloat
*lambda
= span
->array
->lambda
[unit
];
718 float4_array texels
= get_texel_array(swrast
, unit
);
720 /* adjust texture lod (lambda) */
721 if (span
->arrayMask
& SPAN_LAMBDA
) {
722 if (texUnit
->LodBias
+ curObj
->Sampler
.LodBias
!= 0.0F
) {
723 /* apply LOD bias, but don't clamp yet */
724 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ curObj
->Sampler
.LodBias
,
725 -ctx
->Const
.MaxTextureLodBias
,
726 ctx
->Const
.MaxTextureLodBias
);
728 for (i
= 0; i
< span
->end
; i
++) {
733 if (curObj
->Sampler
.MinLod
!= -1000.0 ||
734 curObj
->Sampler
.MaxLod
!= 1000.0) {
735 /* apply LOD clamping to lambda */
736 const GLfloat min
= curObj
->Sampler
.MinLod
;
737 const GLfloat max
= curObj
->Sampler
.MaxLod
;
739 for (i
= 0; i
< span
->end
; i
++) {
740 GLfloat l
= lambda
[i
];
741 lambda
[i
] = CLAMP(l
, min
, max
);
745 else if (curObj
->Sampler
.MaxAnisotropy
> 1.0 &&
746 curObj
->Sampler
.MinFilter
== GL_LINEAR_MIPMAP_LINEAR
) {
747 /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
748 * it requires the current SWspan *span as an additional parameter.
749 * In order to keep the same function signature, the unused lambda
750 * parameter will be modified to actually contain the SWspan pointer.
751 * This is a Hack. To make it right, the texture_sample_func
752 * signature and all implementing functions need to be modified.
754 /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
755 lambda
= (GLfloat
*)span
;
758 /* Sample the texture (span->end = number of fragments) */
759 swrast
->TextureSample
[unit
]( ctx
, texUnit
->_Current
, span
->end
,
760 texcoords
, lambda
, texels
);
762 /* GL_EXT_texture_swizzle */
763 if (curObj
->_Swizzle
!= SWIZZLE_NOOP
) {
764 swizzle_texels(curObj
->_Swizzle
, span
->end
, texels
);
770 * OK, now apply the texture (aka texture combine/blend).
771 * We modify the span->color.rgba values.
773 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
774 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
775 texture_combine(ctx
, unit
, primary_rgba
, swrast
->TexelBuffer
, span
);