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->Sampler.LodBias != 0.0F) {
635 /* apply LOD bias, but don't clamp yet */
636 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->Sampler.LodBias,
637 -ctx->Const.MaxTextureLodBias,
638 ctx->Const.MaxTextureLodBias);
640 for (i = 0; i < span->end; i++) {
645 if (curObj->Sampler.MinLod != -1000.0 ||
646 curObj->Sampler.MaxLod != 1000.0) {
647 /* apply LOD clamping to lambda */
648 const GLfloat min = curObj->Sampler.MinLod;
649 const GLfloat max = curObj->Sampler.MaxLod;
651 for (i = 0; i < span->end; i++) {
652 GLfloat l = lambda[i];
653 lambda[i] = CLAMP(l, min, max);
658 /* Sample the texture (span->end = number of fragments) */
659 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
660 texcoords, lambda, texels );
662 /* manipulate the span values of the bump target
663 not sure this can work correctly even ignoring
664 the problem that channel is unsigned */
665 for (i = 0; i < span->end; i++) {
666 targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
667 rotMatrix01) / targetcoords[i][3];
668 targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
669 rotMatrix11) / targetcoords[i][3];
675 * Must do all texture sampling before combining in order to
676 * accomodate GL_ARB_texture_env_crossbar.
678 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
679 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
680 if (texUnit->_ReallyEnabled &&
681 texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
682 const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
683 span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
684 const struct gl_texture_object *curObj = texUnit->_Current;
685 GLfloat *lambda = span->array->lambda[unit];
686 float4_array texels = get_texel_array(swrast, unit);
688 /* adjust texture lod (lambda) */
689 if (span->arrayMask & SPAN_LAMBDA) {
690 if (texUnit->LodBias + curObj->Sampler.LodBias != 0.0F) {
691 /* apply LOD bias, but don't clamp yet */
692 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->Sampler.LodBias,
693 -ctx->Const.MaxTextureLodBias,
694 ctx->Const.MaxTextureLodBias);
696 for (i = 0; i < span->end; i++) {
701 if (curObj->Sampler.MinLod != -1000.0 ||
702 curObj->Sampler.MaxLod != 1000.0) {
703 /* apply LOD clamping to lambda */
704 const GLfloat min = curObj->Sampler.MinLod;
705 const GLfloat max = curObj->Sampler.MaxLod;
707 for (i = 0; i < span->end; i++) {
708 GLfloat l = lambda[i];
709 lambda[i] = CLAMP(l, min, max);
713 else if (curObj->Sampler.MaxAnisotropy > 1.0 &&
714 curObj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
715 /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
716 * it requires the current SWspan *span as an additional parameter.
717 * In order to keep the same function signature, the unused lambda
718 * parameter will be modified to actually contain the SWspan pointer.
719 * This is a Hack. To make it right, the texture_sample_func
720 * signature and all implementing functions need to be modified.
722 /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
723 lambda = (GLfloat *)span;
726 /* Sample the texture (span->end = number of fragments) */
727 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
728 texcoords, lambda, texels );
730 /* GL_EXT_texture_swizzle */
731 if (curObj->_Swizzle != SWIZZLE_NOOP) {
732 swizzle_texels(curObj->_Swizzle, span->end, texels);
738 * OK, now apply the texture (aka texture combine/blend).
739 * We modify the span->color.rgba values.
741 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
742 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
743 texture_combine( ctx, unit, span->end,