2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
27 #include "main/glheader.h"
28 #include "main/context.h"
29 #include "main/imports.h"
30 #include "main/macros.h"
31 #include "main/pixeltransfer.h"
32 #include "main/samplerobj.h"
33 #include "program/prog_instruction.h"
35 #include "s_context.h"
36 #include "s_texcombine.h"
40 * Pointer to array of float[4]
41 * This type makes the code below more concise and avoids a lot of casting.
43 typedef float (*float4_array
)[4];
47 * Return array of texels for given unit.
49 static inline float4_array
50 get_texel_array(SWcontext
*swrast
, GLuint unit
)
53 return (float4_array
) (swrast
->TexelBuffer
+ unit
* SWRAST_MAX_WIDTH
* 4 * omp_get_num_threads() + (SWRAST_MAX_WIDTH
* 4 * omp_get_thread_num()));
55 return (float4_array
) (swrast
->TexelBuffer
+ unit
* SWRAST_MAX_WIDTH
* 4);
62 * Do texture application for:
63 * GL_EXT_texture_env_combine
64 * GL_ARB_texture_env_combine
65 * GL_EXT_texture_env_dot3
66 * GL_ARB_texture_env_dot3
67 * GL_ATI_texture_env_combine3
68 * GL_NV_texture_env_combine4
69 * conventional GL texture env modes
71 * \param ctx rendering context
72 * \param unit the texture combiner unit
73 * \param primary_rgba incoming fragment color array
74 * \param texelBuffer pointer to texel colors for all texture units
76 * \param span two fields are used in this function:
77 * span->end: number of fragments to process
78 * span->array->rgba: incoming/result fragment colors
81 texture_combine( struct gl_context
*ctx
, GLuint unit
,
82 const float4_array primary_rgba
,
83 const GLfloat
*texelBuffer
,
86 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
87 const struct gl_texture_unit
*textureUnit
= &(ctx
->Texture
.Unit
[unit
]);
88 const struct gl_tex_env_combine_state
*combine
= textureUnit
->_CurrentCombine
;
89 float4_array argRGB
[MAX_COMBINER_TERMS
];
90 float4_array argA
[MAX_COMBINER_TERMS
];
91 const GLfloat scaleRGB
= (GLfloat
) (1 << combine
->ScaleShiftRGB
);
92 const GLfloat scaleA
= (GLfloat
) (1 << combine
->ScaleShiftA
);
93 const GLuint numArgsRGB
= combine
->_NumArgsRGB
;
94 const GLuint numArgsA
= combine
->_NumArgsA
;
95 float4_array ccolor
[4], rgba
;
98 GLchan (*rgbaChan
)[4] = span
->array
->rgba
;
100 /* alloc temp pixel buffers */
101 rgba
= malloc(4 * n
* sizeof(GLfloat
));
103 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
107 for (i
= 0; i
< numArgsRGB
|| i
< numArgsA
; i
++) {
108 ccolor
[i
] = malloc(4 * n
* sizeof(GLfloat
));
114 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
120 for (i
= 0; i
< n
; i
++) {
121 rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][RCOMP
]);
122 rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][GCOMP
]);
123 rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][BCOMP
]);
124 rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(rgbaChan
[i
][ACOMP
]);
128 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
131 combine->SourceRGB[0],
133 combine->SourceRGB[1],
134 combine->SourceA[1]);
138 * Do operand setup for up to 4 operands. Loop over the terms.
140 for (term
= 0; term
< numArgsRGB
; term
++) {
141 const GLenum srcRGB
= combine
->SourceRGB
[term
];
142 const GLenum operandRGB
= combine
->OperandRGB
[term
];
146 argRGB
[term
] = get_texel_array(swrast
, unit
);
148 case GL_PRIMARY_COLOR
:
149 argRGB
[term
] = primary_rgba
;
156 float4_array c
= ccolor
[term
];
157 GLfloat red
= textureUnit
->EnvColor
[0];
158 GLfloat green
= textureUnit
->EnvColor
[1];
159 GLfloat blue
= textureUnit
->EnvColor
[2];
160 GLfloat alpha
= textureUnit
->EnvColor
[3];
161 for (i
= 0; i
< n
; i
++) {
162 ASSIGN_4V(c
[i
], red
, green
, blue
, alpha
);
164 argRGB
[term
] = ccolor
[term
];
167 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
171 float4_array c
= ccolor
[term
];
172 for (i
= 0; i
< n
; i
++) {
173 ASSIGN_4V(c
[i
], 0.0F
, 0.0F
, 0.0F
, 0.0F
);
175 argRGB
[term
] = ccolor
[term
];
180 float4_array c
= ccolor
[term
];
181 for (i
= 0; i
< n
; i
++) {
182 ASSIGN_4V(c
[i
], 1.0F
, 1.0F
, 1.0F
, 1.0F
);
184 argRGB
[term
] = ccolor
[term
];
188 /* ARB_texture_env_crossbar source */
190 const GLuint srcUnit
= srcRGB
- GL_TEXTURE0
;
191 assert(srcUnit
< ctx
->Const
.MaxTextureUnits
);
192 if (!ctx
->Texture
.Unit
[srcUnit
]._Current
)
194 argRGB
[term
] = get_texel_array(swrast
, srcUnit
);
198 if (operandRGB
!= GL_SRC_COLOR
) {
199 float4_array src
= argRGB
[term
];
200 float4_array dst
= ccolor
[term
];
202 /* point to new arg[term] storage */
203 argRGB
[term
] = ccolor
[term
];
205 switch (operandRGB
) {
206 case GL_ONE_MINUS_SRC_COLOR
:
207 for (i
= 0; i
< n
; i
++) {
208 dst
[i
][RCOMP
] = 1.0F
- src
[i
][RCOMP
];
209 dst
[i
][GCOMP
] = 1.0F
- src
[i
][GCOMP
];
210 dst
[i
][BCOMP
] = 1.0F
- src
[i
][BCOMP
];
214 for (i
= 0; i
< n
; i
++) {
217 dst
[i
][BCOMP
] = src
[i
][ACOMP
];
220 case GL_ONE_MINUS_SRC_ALPHA
:
221 for (i
= 0; i
< n
; i
++) {
224 dst
[i
][BCOMP
] = 1.0F
- src
[i
][ACOMP
];
228 _mesa_problem(ctx
, "Bad operandRGB");
234 * Set up the argA[term] pointers
236 for (term
= 0; term
< numArgsA
; term
++) {
237 const GLenum srcA
= combine
->SourceA
[term
];
238 const GLenum operandA
= combine
->OperandA
[term
];
242 argA
[term
] = get_texel_array(swrast
, unit
);
244 case GL_PRIMARY_COLOR
:
245 argA
[term
] = primary_rgba
;
252 float4_array c
= ccolor
[term
];
253 GLfloat alpha
= textureUnit
->EnvColor
[3];
254 for (i
= 0; i
< n
; i
++)
256 argA
[term
] = ccolor
[term
];
259 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
263 float4_array c
= ccolor
[term
];
264 for (i
= 0; i
< n
; i
++)
266 argA
[term
] = ccolor
[term
];
271 float4_array c
= ccolor
[term
];
272 for (i
= 0; i
< n
; i
++)
274 argA
[term
] = ccolor
[term
];
278 /* ARB_texture_env_crossbar source */
280 const GLuint srcUnit
= srcA
- GL_TEXTURE0
;
281 assert(srcUnit
< ctx
->Const
.MaxTextureUnits
);
282 if (!ctx
->Texture
.Unit
[srcUnit
]._Current
)
284 argA
[term
] = get_texel_array(swrast
, srcUnit
);
288 if (operandA
== GL_ONE_MINUS_SRC_ALPHA
) {
289 float4_array src
= argA
[term
];
290 float4_array dst
= ccolor
[term
];
291 argA
[term
] = ccolor
[term
];
292 for (i
= 0; i
< n
; i
++) {
293 dst
[i
][ACOMP
] = 1.0F
- src
[i
][ACOMP
];
298 /* RGB channel combine */
300 float4_array arg0
= argRGB
[0];
301 float4_array arg1
= argRGB
[1];
302 float4_array arg2
= argRGB
[2];
303 float4_array arg3
= argRGB
[3];
305 switch (combine
->ModeRGB
) {
307 for (i
= 0; i
< n
; i
++) {
308 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * scaleRGB
;
309 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * scaleRGB
;
310 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * scaleRGB
;
314 for (i
= 0; i
< n
; i
++) {
315 rgba
[i
][RCOMP
] = arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] * scaleRGB
;
316 rgba
[i
][GCOMP
] = arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] * scaleRGB
;
317 rgba
[i
][BCOMP
] = arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] * scaleRGB
;
321 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
322 /* (a * b) + (c * d) */
323 for (i
= 0; i
< n
; i
++) {
324 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
325 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
]) * scaleRGB
;
326 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
327 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
]) * scaleRGB
;
328 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
329 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
]) * scaleRGB
;
333 /* 2-term addition */
334 for (i
= 0; i
< n
; i
++) {
335 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
]) * scaleRGB
;
336 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
]) * scaleRGB
;
337 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
]) * scaleRGB
;
342 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
343 /* (a * b) + (c * d) - 0.5 */
344 for (i
= 0; i
< n
; i
++) {
345 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg1
[i
][RCOMP
] +
346 arg2
[i
][RCOMP
] * arg3
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
347 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg1
[i
][GCOMP
] +
348 arg2
[i
][GCOMP
] * arg3
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
349 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg1
[i
][BCOMP
] +
350 arg2
[i
][BCOMP
] * arg3
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
354 for (i
= 0; i
< n
; i
++) {
355 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] + arg1
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
356 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] + arg1
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
357 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] + arg1
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
362 for (i
= 0; i
< n
; i
++) {
363 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
] +
364 arg1
[i
][RCOMP
] * (1.0F
- arg2
[i
][RCOMP
])) * scaleRGB
;
365 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
] +
366 arg1
[i
][GCOMP
] * (1.0F
- arg2
[i
][GCOMP
])) * scaleRGB
;
367 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
] +
368 arg1
[i
][BCOMP
] * (1.0F
- arg2
[i
][BCOMP
])) * scaleRGB
;
372 for (i
= 0; i
< n
; i
++) {
373 rgba
[i
][RCOMP
] = (arg0
[i
][RCOMP
] - arg1
[i
][RCOMP
]) * scaleRGB
;
374 rgba
[i
][GCOMP
] = (arg0
[i
][GCOMP
] - arg1
[i
][GCOMP
]) * scaleRGB
;
375 rgba
[i
][BCOMP
] = (arg0
[i
][BCOMP
] - arg1
[i
][BCOMP
]) * scaleRGB
;
378 case GL_DOT3_RGB_EXT
:
379 case GL_DOT3_RGBA_EXT
:
380 /* Do not scale the result by 1 2 or 4 */
381 for (i
= 0; i
< n
; i
++) {
382 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
383 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
384 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
386 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
387 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
392 /* DO scale the result by 1 2 or 4 */
393 for (i
= 0; i
< n
; i
++) {
394 GLfloat dot
= ((arg0
[i
][RCOMP
] - 0.5F
) * (arg1
[i
][RCOMP
] - 0.5F
) +
395 (arg0
[i
][GCOMP
] - 0.5F
) * (arg1
[i
][GCOMP
] - 0.5F
) +
396 (arg0
[i
][BCOMP
] - 0.5F
) * (arg1
[i
][BCOMP
] - 0.5F
))
398 dot
= CLAMP(dot
, 0.0F
, 1.0F
);
399 rgba
[i
][RCOMP
] = rgba
[i
][GCOMP
] = rgba
[i
][BCOMP
] = dot
;
402 case GL_MODULATE_ADD_ATI
:
403 for (i
= 0; i
< n
; i
++) {
404 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
405 arg1
[i
][RCOMP
]) * scaleRGB
;
406 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
407 arg1
[i
][GCOMP
]) * scaleRGB
;
408 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
409 arg1
[i
][BCOMP
]) * scaleRGB
;
412 case GL_MODULATE_SIGNED_ADD_ATI
:
413 for (i
= 0; i
< n
; i
++) {
414 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) +
415 arg1
[i
][RCOMP
] - 0.5F
) * scaleRGB
;
416 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) +
417 arg1
[i
][GCOMP
] - 0.5F
) * scaleRGB
;
418 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) +
419 arg1
[i
][BCOMP
] - 0.5F
) * scaleRGB
;
422 case GL_MODULATE_SUBTRACT_ATI
:
423 for (i
= 0; i
< n
; i
++) {
424 rgba
[i
][RCOMP
] = ((arg0
[i
][RCOMP
] * arg2
[i
][RCOMP
]) -
425 arg1
[i
][RCOMP
]) * scaleRGB
;
426 rgba
[i
][GCOMP
] = ((arg0
[i
][GCOMP
] * arg2
[i
][GCOMP
]) -
427 arg1
[i
][GCOMP
]) * scaleRGB
;
428 rgba
[i
][BCOMP
] = ((arg0
[i
][BCOMP
] * arg2
[i
][BCOMP
]) -
429 arg1
[i
][BCOMP
]) * scaleRGB
;
433 _mesa_problem(ctx
, "invalid combine mode");
437 /* Alpha channel combine */
439 float4_array arg0
= argA
[0];
440 float4_array arg1
= argA
[1];
441 float4_array arg2
= argA
[2];
442 float4_array arg3
= argA
[3];
444 switch (combine
->ModeA
) {
446 for (i
= 0; i
< n
; i
++) {
447 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * scaleA
;
451 for (i
= 0; i
< n
; i
++) {
452 rgba
[i
][ACOMP
] = arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] * scaleA
;
456 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
457 /* (a * b) + (c * d) */
458 for (i
= 0; i
< n
; i
++) {
459 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
460 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
]) * scaleA
;
465 for (i
= 0; i
< n
; i
++) {
466 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
]) * scaleA
;
471 if (textureUnit
->EnvMode
== GL_COMBINE4_NV
) {
472 /* (a * b) + (c * d) - 0.5 */
473 for (i
= 0; i
< n
; i
++) {
474 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg1
[i
][ACOMP
] +
475 arg2
[i
][ACOMP
] * arg3
[i
][ACOMP
] -
481 for (i
= 0; i
< n
; i
++) {
482 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] + arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
487 for (i
= 0; i
< n
; i
++) {
488 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
] +
489 arg1
[i
][ACOMP
] * (1.0F
- arg2
[i
][ACOMP
]))
494 for (i
= 0; i
< n
; i
++) {
495 rgba
[i
][ACOMP
] = (arg0
[i
][ACOMP
] - arg1
[i
][ACOMP
]) * scaleA
;
498 case GL_MODULATE_ADD_ATI
:
499 for (i
= 0; i
< n
; i
++) {
500 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
501 + arg1
[i
][ACOMP
]) * scaleA
;
504 case GL_MODULATE_SIGNED_ADD_ATI
:
505 for (i
= 0; i
< n
; i
++) {
506 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
]) +
507 arg1
[i
][ACOMP
] - 0.5F
) * scaleA
;
510 case GL_MODULATE_SUBTRACT_ATI
:
511 for (i
= 0; i
< n
; i
++) {
512 rgba
[i
][ACOMP
] = ((arg0
[i
][ACOMP
] * arg2
[i
][ACOMP
])
513 - arg1
[i
][ACOMP
]) * scaleA
;
517 _mesa_problem(ctx
, "invalid combine mode");
521 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
522 * This is kind of a kludge. It would have been better if the spec
523 * were written such that the GL_COMBINE_ALPHA value could be set to
526 if (combine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
527 combine
->ModeRGB
== GL_DOT3_RGBA
) {
528 for (i
= 0; i
< n
; i
++) {
529 rgba
[i
][ACOMP
] = rgba
[i
][RCOMP
];
533 for (i
= 0; i
< n
; i
++) {
534 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][RCOMP
], rgba
[i
][RCOMP
]);
535 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][GCOMP
], rgba
[i
][GCOMP
]);
536 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][BCOMP
], rgba
[i
][BCOMP
]);
537 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan
[i
][ACOMP
], rgba
[i
][ACOMP
]);
539 /* The span->array->rgba values are of CHAN type so set
540 * span->array->ChanType field accordingly.
542 span
->array
->ChanType
= CHAN_TYPE
;
545 for (i
= 0; i
< numArgsRGB
|| i
< numArgsA
; i
++) {
553 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
554 * See GL_EXT_texture_swizzle.
557 swizzle_texels(GLuint swizzle
, GLuint count
, float4_array texels
)
559 const GLuint swzR
= GET_SWZ(swizzle
, 0);
560 const GLuint swzG
= GET_SWZ(swizzle
, 1);
561 const GLuint swzB
= GET_SWZ(swizzle
, 2);
562 const GLuint swzA
= GET_SWZ(swizzle
, 3);
566 vector
[SWIZZLE_ZERO
] = 0;
567 vector
[SWIZZLE_ONE
] = 1.0F
;
569 for (i
= 0; i
< count
; i
++) {
570 vector
[SWIZZLE_X
] = texels
[i
][0];
571 vector
[SWIZZLE_Y
] = texels
[i
][1];
572 vector
[SWIZZLE_Z
] = texels
[i
][2];
573 vector
[SWIZZLE_W
] = texels
[i
][3];
574 texels
[i
][RCOMP
] = vector
[swzR
];
575 texels
[i
][GCOMP
] = vector
[swzG
];
576 texels
[i
][BCOMP
] = vector
[swzB
];
577 texels
[i
][ACOMP
] = vector
[swzA
];
583 * Apply texture mapping to a span of fragments.
586 _swrast_texture_span( struct gl_context
*ctx
, SWspan
*span
)
588 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
589 float4_array primary_rgba
;
592 if (!swrast
->TexelBuffer
) {
594 const GLint maxThreads
= omp_get_max_threads();
596 /* TexelBuffer memory allocation needs to be done in a critical section
597 * as this code runs in a parallel loop.
598 * When entering the section, first check if TexelBuffer has been
599 * initialized already by another thread while this thread was waiting.
602 if (!swrast
->TexelBuffer
) {
604 const GLint maxThreads
= 1;
607 /* TexelBuffer is also global and normally shared by all SWspan
608 * instances; when running with multiple threads, create one per
611 swrast
->TexelBuffer
=
612 malloc(ctx
->Const
.Program
[MESA_SHADER_FRAGMENT
].MaxTextureImageUnits
* maxThreads
*
613 SWRAST_MAX_WIDTH
* 4 * sizeof(GLfloat
));
615 } /* critical section */
618 if (!swrast
->TexelBuffer
) {
619 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_combine");
624 primary_rgba
= malloc(span
->end
* 4 * sizeof(GLfloat
));
627 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "texture_span");
631 assert(span
->end
<= SWRAST_MAX_WIDTH
);
634 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
636 if (swrast
->_TextureCombinePrimary
) {
638 for (i
= 0; i
< span
->end
; i
++) {
639 primary_rgba
[i
][RCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][RCOMP
]);
640 primary_rgba
[i
][GCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][GCOMP
]);
641 primary_rgba
[i
][BCOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][BCOMP
]);
642 primary_rgba
[i
][ACOMP
] = CHAN_TO_FLOAT(span
->array
->rgba
[i
][ACOMP
]);
647 * Must do all texture sampling before combining in order to
648 * accommodate GL_ARB_texture_env_crossbar.
650 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
651 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
652 if (texUnit
->_Current
) {
653 const GLfloat (*texcoords
)[4] = (const GLfloat (*)[4])
654 span
->array
->attribs
[VARYING_SLOT_TEX0
+ unit
];
655 const struct gl_texture_object
*curObj
= texUnit
->_Current
;
656 const struct gl_sampler_object
*samp
= _mesa_get_samplerobj(ctx
, unit
);
657 GLfloat
*lambda
= span
->array
->lambda
[unit
];
658 float4_array texels
= get_texel_array(swrast
, unit
);
660 /* adjust texture lod (lambda) */
661 if (span
->arrayMask
& SPAN_LAMBDA
) {
662 if (texUnit
->LodBias
+ samp
->LodBias
!= 0.0F
) {
663 /* apply LOD bias, but don't clamp yet */
664 const GLfloat bias
= CLAMP(texUnit
->LodBias
+ samp
->LodBias
,
665 -ctx
->Const
.MaxTextureLodBias
,
666 ctx
->Const
.MaxTextureLodBias
);
668 for (i
= 0; i
< span
->end
; i
++) {
673 if (samp
->MinLod
!= -1000.0F
||
674 samp
->MaxLod
!= 1000.0F
) {
675 /* apply LOD clamping to lambda */
676 const GLfloat min
= samp
->MinLod
;
677 const GLfloat max
= samp
->MaxLod
;
679 for (i
= 0; i
< span
->end
; i
++) {
680 GLfloat l
= lambda
[i
];
681 lambda
[i
] = CLAMP(l
, min
, max
);
685 else if (samp
->MaxAnisotropy
> 1.0F
&&
686 samp
->MinFilter
== GL_LINEAR_MIPMAP_LINEAR
) {
687 /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
688 * it requires the current SWspan *span as an additional parameter.
689 * In order to keep the same function signature, the unused lambda
690 * parameter will be modified to actually contain the SWspan pointer.
691 * This is a Hack. To make it right, the texture_sample_func
692 * signature and all implementing functions need to be modified.
694 /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
695 lambda
= (GLfloat
*)span
;
698 /* Sample the texture (span->end = number of fragments) */
699 swrast
->TextureSample
[unit
]( ctx
, samp
,
700 ctx
->Texture
.Unit
[unit
]._Current
,
701 span
->end
, texcoords
, lambda
, texels
);
703 /* GL_EXT_texture_swizzle */
704 if (curObj
->_Swizzle
!= SWIZZLE_NOOP
) {
705 swizzle_texels(curObj
->_Swizzle
, span
->end
, texels
);
711 * OK, now apply the texture (aka texture combine/blend).
712 * We modify the span->color.rgba values.
714 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
715 if (ctx
->Texture
.Unit
[unit
]._Current
)
716 texture_combine(ctx
, unit
, primary_rgba
, swrast
->TexelBuffer
, span
);