s_texcombine.c revision 7aed2b0c30c6d29d70efd2402a68a8e3de98418c
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.5 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 7 * 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: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 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. 24 */ 25 26 27#include "main/glheader.h" 28#include "main/context.h" 29#include "main/colormac.h" 30#include "main/image.h" 31#include "main/imports.h" 32#include "main/pixel.h" 33#include "shader/prog_instruction.h" 34 35#include "s_context.h" 36#include "s_texcombine.h" 37 38 39/** 40 * Pointer to array of float[4] 41 * This type makes the code below more concise and avoids a lot of casting. 42 */ 43typedef float (*float4_array)[4]; 44 45 46/** 47 * Return array of texels for given unit. 48 */ 49static INLINE float4_array 50get_texel_array(const GLfloat *texelBuffer, GLuint unit, GLuint numTexels) 51{ 52 return (float4_array) 53 (texelBuffer + unit * numTexels * 4 * sizeof(GLfloat)); 54} 55 56 57 58/** 59 * Do texture application for: 60 * GL_EXT_texture_env_combine 61 * GL_ARB_texture_env_combine 62 * GL_EXT_texture_env_dot3 63 * GL_ARB_texture_env_dot3 64 * GL_ATI_texture_env_combine3 65 * GL_NV_texture_env_combine4 66 * conventional GL texture env modes 67 * 68 * \param ctx rendering context 69 * \param unit the texture combiner unit 70 * \param n number of fragments to process (span width) 71 * \param primary_rgba incoming fragment color array 72 * \param texelBuffer pointer to texel colors for all texture units 73 * 74 * \param rgba incoming/result fragment colors 75 */ 76static void 77texture_combine( const GLcontext *ctx, GLuint unit, GLuint n, 78 const float4_array primary_rgba, 79 const GLfloat *texelBuffer, 80 GLchan (*rgbaChan)[4] ) 81{ 82 const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]); 83 const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine; 84 float4_array argRGB[MAX_COMBINER_TERMS]; 85 float4_array argA[MAX_COMBINER_TERMS]; 86 const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB); 87 const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA); 88 const GLuint numArgsRGB = combine->_NumArgsRGB; 89 const GLuint numArgsA = combine->_NumArgsA; 90 GLfloat ccolor[MAX_COMBINER_TERMS][MAX_WIDTH][4]; /* temp color buffers */ 91 GLfloat rgba[MAX_WIDTH][4]; 92 GLuint i, term; 93 94 for (i = 0; i < n; i++) { 95 rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]); 96 rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]); 97 rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]); 98 rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]); 99 } 100 101 /* 102 printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n", 103 combine->ModeRGB, 104 combine->ModeA, 105 combine->SourceRGB[0], 106 combine->SourceA[0], 107 combine->SourceRGB[1], 108 combine->SourceA[1]); 109 */ 110 111 /* 112 * Do operand setup for up to 4 operands. Loop over the terms. 113 */ 114 for (term = 0; term < numArgsRGB; term++) { 115 const GLenum srcRGB = combine->SourceRGB[term]; 116 const GLenum operandRGB = combine->OperandRGB[term]; 117 118 switch (srcRGB) { 119 case GL_TEXTURE: 120 argRGB[term] = get_texel_array(texelBuffer, unit, n); 121 break; 122 case GL_PRIMARY_COLOR: 123 argRGB[term] = primary_rgba; 124 break; 125 case GL_PREVIOUS: 126 argRGB[term] = rgba; 127 break; 128 case GL_CONSTANT: 129 { 130 float4_array c = ccolor[term]; 131 GLfloat red = textureUnit->EnvColor[0]; 132 GLfloat green = textureUnit->EnvColor[1]; 133 GLfloat blue = textureUnit->EnvColor[2]; 134 GLfloat alpha = textureUnit->EnvColor[3]; 135 for (i = 0; i < n; i++) { 136 ASSIGN_4V(c[i], red, green, blue, alpha); 137 } 138 argRGB[term] = ccolor[term]; 139 } 140 break; 141 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources. 142 */ 143 case GL_ZERO: 144 { 145 float4_array c = ccolor[term]; 146 for (i = 0; i < n; i++) { 147 ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F); 148 } 149 argRGB[term] = ccolor[term]; 150 } 151 break; 152 case GL_ONE: 153 { 154 float4_array c = ccolor[term]; 155 for (i = 0; i < n; i++) { 156 ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F); 157 } 158 argRGB[term] = ccolor[term]; 159 } 160 break; 161 default: 162 /* ARB_texture_env_crossbar source */ 163 { 164 const GLuint srcUnit = srcRGB - GL_TEXTURE0; 165 ASSERT(srcUnit < ctx->Const.MaxTextureUnits); 166 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled) 167 return; 168 argRGB[term] = get_texel_array(texelBuffer, srcUnit, n); 169 } 170 } 171 172 if (operandRGB != GL_SRC_COLOR) { 173 float4_array src = argRGB[term]; 174 float4_array dst = ccolor[term]; 175 176 /* point to new arg[term] storage */ 177 argRGB[term] = ccolor[term]; 178 179 switch (operandRGB) { 180 case GL_ONE_MINUS_SRC_COLOR: 181 for (i = 0; i < n; i++) { 182 dst[i][RCOMP] = 1.0F - src[i][RCOMP]; 183 dst[i][GCOMP] = 1.0F - src[i][GCOMP]; 184 dst[i][BCOMP] = 1.0F - src[i][BCOMP]; 185 } 186 break; 187 case GL_SRC_ALPHA: 188 for (i = 0; i < n; i++) { 189 dst[i][RCOMP] = 190 dst[i][GCOMP] = 191 dst[i][BCOMP] = src[i][ACOMP]; 192 } 193 break; 194 case GL_ONE_MINUS_SRC_ALPHA: 195 for (i = 0; i < n; i++) { 196 dst[i][RCOMP] = 197 dst[i][GCOMP] = 198 dst[i][BCOMP] = 1.0F - src[i][ACOMP]; 199 } 200 break; 201 default: 202 _mesa_problem(ctx, "Bad operandRGB"); 203 } 204 } 205 } 206 207 /* 208 * Set up the argA[term] pointers 209 */ 210 for (term = 0; term < numArgsA; term++) { 211 const GLenum srcA = combine->SourceA[term]; 212 const GLenum operandA = combine->OperandA[term]; 213 214 switch (srcA) { 215 case GL_TEXTURE: 216 argA[term] = get_texel_array(texelBuffer, unit, n); 217 break; 218 case GL_PRIMARY_COLOR: 219 argA[term] = primary_rgba; 220 break; 221 case GL_PREVIOUS: 222 argA[term] = rgba; 223 break; 224 case GL_CONSTANT: 225 { 226 float4_array c = ccolor[term]; 227 GLfloat alpha = textureUnit->EnvColor[3]; 228 for (i = 0; i < n; i++) 229 c[i][ACOMP] = alpha; 230 argA[term] = ccolor[term]; 231 } 232 break; 233 /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources. 234 */ 235 case GL_ZERO: 236 { 237 float4_array c = ccolor[term]; 238 for (i = 0; i < n; i++) 239 c[i][ACOMP] = 0.0F; 240 argA[term] = ccolor[term]; 241 } 242 break; 243 case GL_ONE: 244 { 245 float4_array c = ccolor[term]; 246 for (i = 0; i < n; i++) 247 c[i][ACOMP] = 1.0F; 248 argA[term] = ccolor[term]; 249 } 250 break; 251 default: 252 /* ARB_texture_env_crossbar source */ 253 { 254 const GLuint srcUnit = srcA - GL_TEXTURE0; 255 ASSERT(srcUnit < ctx->Const.MaxTextureUnits); 256 if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled) 257 return; 258 argA[term] = get_texel_array(texelBuffer, srcUnit, n); 259 } 260 } 261 262 if (operandA == GL_ONE_MINUS_SRC_ALPHA) { 263 float4_array src = argA[term]; 264 float4_array dst = ccolor[term]; 265 argA[term] = ccolor[term]; 266 for (i = 0; i < n; i++) { 267 dst[i][ACOMP] = 1.0F - src[i][ACOMP]; 268 } 269 } 270 } 271 272 /* RGB channel combine */ 273 { 274 float4_array arg0 = argRGB[0]; 275 float4_array arg1 = argRGB[1]; 276 float4_array arg2 = argRGB[2]; 277 float4_array arg3 = argRGB[3]; 278 279 switch (combine->ModeRGB) { 280 case GL_REPLACE: 281 for (i = 0; i < n; i++) { 282 rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB; 283 rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB; 284 rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB; 285 } 286 break; 287 case GL_MODULATE: 288 for (i = 0; i < n; i++) { 289 rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB; 290 rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB; 291 rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB; 292 } 293 break; 294 case GL_ADD: 295 if (textureUnit->EnvMode == GL_COMBINE4_NV) { 296 /* (a * b) + (c * d) */ 297 for (i = 0; i < n; i++) { 298 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] + 299 arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB; 300 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] + 301 arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB; 302 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] + 303 arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB; 304 } 305 } 306 else { 307 /* 2-term addition */ 308 for (i = 0; i < n; i++) { 309 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB; 310 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB; 311 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB; 312 } 313 } 314 break; 315 case GL_ADD_SIGNED: 316 if (textureUnit->EnvMode == GL_COMBINE4_NV) { 317 /* (a * b) + (c * d) - 0.5 */ 318 for (i = 0; i < n; i++) { 319 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] * 320 arg2[i][RCOMP] + arg3[i][RCOMP] - 0.5) * scaleRGB; 321 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] * 322 arg2[i][GCOMP] + arg3[i][GCOMP] - 0.5) * scaleRGB; 323 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] * 324 arg2[i][BCOMP] + arg3[i][BCOMP] - 0.5) * scaleRGB; 325 } 326 } 327 else { 328 for (i = 0; i < n; i++) { 329 rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * scaleRGB; 330 rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * scaleRGB; 331 rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * scaleRGB; 332 } 333 } 334 break; 335 case GL_INTERPOLATE: 336 for (i = 0; i < n; i++) { 337 rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] + 338 arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB; 339 rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] + 340 arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB; 341 rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] + 342 arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB; 343 } 344 break; 345 case GL_SUBTRACT: 346 for (i = 0; i < n; i++) { 347 rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB; 348 rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB; 349 rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB; 350 } 351 break; 352 case GL_DOT3_RGB_EXT: 353 case GL_DOT3_RGBA_EXT: 354 /* Do not scale the result by 1 2 or 4 */ 355 for (i = 0; i < n; i++) { 356 GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) + 357 (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) + 358 (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F)) 359 * 4.0F; 360 dot = CLAMP(dot, 0.0F, 1.0F); 361 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot; 362 } 363 break; 364 case GL_DOT3_RGB: 365 case GL_DOT3_RGBA: 366 /* DO scale the result by 1 2 or 4 */ 367 for (i = 0; i < n; i++) { 368 GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) + 369 (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) + 370 (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F)) 371 * 4.0F * scaleRGB; 372 dot = CLAMP(dot, 0.0, 1.0F); 373 rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot; 374 } 375 break; 376 case GL_MODULATE_ADD_ATI: 377 for (i = 0; i < n; i++) { 378 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + 379 arg1[i][RCOMP]) * scaleRGB; 380 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + 381 arg1[i][GCOMP]) * scaleRGB; 382 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + 383 arg1[i][BCOMP]) * scaleRGB; 384 } 385 break; 386 case GL_MODULATE_SIGNED_ADD_ATI: 387 for (i = 0; i < n; i++) { 388 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) + 389 arg1[i][RCOMP] - 0.5) * scaleRGB; 390 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) + 391 arg1[i][GCOMP] - 0.5) * scaleRGB; 392 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) + 393 arg1[i][BCOMP] - 0.5) * scaleRGB; 394 } 395 break; 396 case GL_MODULATE_SUBTRACT_ATI: 397 for (i = 0; i < n; i++) { 398 rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) - 399 arg1[i][RCOMP]) * scaleRGB; 400 rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) - 401 arg1[i][GCOMP]) * scaleRGB; 402 rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) - 403 arg1[i][BCOMP]) * scaleRGB; 404 } 405 break; 406 case GL_BUMP_ENVMAP_ATI: 407 { 408 /* this produces a fixed rgba color, and the coord calc is done elsewhere */ 409 for (i = 0; i < n; i++) { 410 /* rgba result is 0,0,0,1 */ 411#if CHAN_TYPE == GL_FLOAT 412 rgba[i][RCOMP] = 0.0; 413 rgba[i][GCOMP] = 0.0; 414 rgba[i][BCOMP] = 0.0; 415 rgba[i][ACOMP] = 1.0; 416#else 417 rgba[i][RCOMP] = 0; 418 rgba[i][GCOMP] = 0; 419 rgba[i][BCOMP] = 0; 420 rgba[i][ACOMP] = CHAN_MAX; 421#endif 422 } 423 } 424 return; /* no alpha processing */ 425 default: 426 _mesa_problem(ctx, "invalid combine mode"); 427 } 428 } 429 430 /* Alpha channel combine */ 431 { 432 float4_array arg0 = argA[0]; 433 float4_array arg1 = argA[1]; 434 float4_array arg2 = argA[2]; 435 float4_array arg3 = argA[3]; 436 437 switch (combine->ModeA) { 438 case GL_REPLACE: 439 for (i = 0; i < n; i++) { 440 rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA; 441 } 442 break; 443 case GL_MODULATE: 444 for (i = 0; i < n; i++) { 445 rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA; 446 } 447 break; 448 case GL_ADD: 449 if (textureUnit->EnvMode == GL_COMBINE4_NV) { 450 /* (a * b) + (c * d) */ 451 for (i = 0; i < n; i++) { 452 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] + 453 arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA; 454 } 455 } 456 else { 457 /* two-term add */ 458 for (i = 0; i < n; i++) { 459 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA; 460 } 461 } 462 break; 463 case GL_ADD_SIGNED: 464 if (textureUnit->EnvMode == GL_COMBINE4_NV) { 465 /* (a * b) + (c * d) - 0.5 */ 466 for (i = 0; i < n; i++) { 467 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] + 468 arg2[i][ACOMP] * arg3[i][ACOMP] - 469 0.5) * scaleA; 470 } 471 } 472 else { 473 /* a + b - 0.5 */ 474 for (i = 0; i < n; i++) { 475 rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA; 476 } 477 } 478 break; 479 case GL_INTERPOLATE: 480 for (i = 0; i < n; i++) { 481 rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] + 482 arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP])) 483 * scaleA; 484 } 485 break; 486 case GL_SUBTRACT: 487 for (i = 0; i < n; i++) { 488 rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA; 489 } 490 break; 491 case GL_MODULATE_ADD_ATI: 492 for (i = 0; i < n; i++) { 493 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) 494 + arg1[i][ACOMP]) * scaleA; 495 } 496 break; 497 case GL_MODULATE_SIGNED_ADD_ATI: 498 for (i = 0; i < n; i++) { 499 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) + 500 arg1[i][ACOMP] - 0.5F) * scaleA; 501 } 502 break; 503 case GL_MODULATE_SUBTRACT_ATI: 504 for (i = 0; i < n; i++) { 505 rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) 506 - arg1[i][ACOMP]) * scaleA; 507 } 508 break; 509 default: 510 _mesa_problem(ctx, "invalid combine mode"); 511 } 512 } 513 514 /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining. 515 * This is kind of a kludge. It would have been better if the spec 516 * were written such that the GL_COMBINE_ALPHA value could be set to 517 * GL_DOT3. 518 */ 519 if (combine->ModeRGB == GL_DOT3_RGBA_EXT || 520 combine->ModeRGB == GL_DOT3_RGBA) { 521 for (i = 0; i < n; i++) { 522 rgba[i][ACOMP] = rgba[i][RCOMP]; 523 } 524 } 525 526 for (i = 0; i < n; i++) { 527 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]); 528 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]); 529 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]); 530 UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]); 531 } 532} 533 534 535/** 536 * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels. 537 * See GL_EXT_texture_swizzle. 538 */ 539static void 540swizzle_texels(GLuint swizzle, GLuint count, float4_array texels) 541{ 542 const GLuint swzR = GET_SWZ(swizzle, 0); 543 const GLuint swzG = GET_SWZ(swizzle, 1); 544 const GLuint swzB = GET_SWZ(swizzle, 2); 545 const GLuint swzA = GET_SWZ(swizzle, 3); 546 GLfloat vector[6]; 547 GLuint i; 548 549 vector[SWIZZLE_ZERO] = 0; 550 vector[SWIZZLE_ONE] = 1.0F; 551 552 for (i = 0; i < count; i++) { 553 vector[SWIZZLE_X] = texels[i][0]; 554 vector[SWIZZLE_Y] = texels[i][1]; 555 vector[SWIZZLE_Z] = texels[i][2]; 556 vector[SWIZZLE_W] = texels[i][3]; 557 texels[i][RCOMP] = vector[swzR]; 558 texels[i][GCOMP] = vector[swzG]; 559 texels[i][BCOMP] = vector[swzB]; 560 texels[i][ACOMP] = vector[swzA]; 561 } 562} 563 564 565/** 566 * Apply texture mapping to a span of fragments. 567 */ 568void 569_swrast_texture_span( GLcontext *ctx, SWspan *span ) 570{ 571 SWcontext *swrast = SWRAST_CONTEXT(ctx); 572 GLfloat primary_rgba[MAX_WIDTH][4]; 573 GLuint unit; 574 575 ASSERT(span->end <= MAX_WIDTH); 576 577 /* 578 * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR) 579 */ 580 if (swrast->_TextureCombinePrimary) { 581 GLuint i; 582 for (i = 0; i < span->end; i++) { 583 primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]); 584 primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]); 585 primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]); 586 primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]); 587 } 588 } 589 590 /* First must sample all bump maps */ 591 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 592 if (ctx->Texture.Unit[unit]._ReallyEnabled && 593 ctx->Texture.Unit[unit]._CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) { 594 const GLfloat (*texcoords)[4] 595 = (const GLfloat (*)[4]) 596 span->array->attribs[FRAG_ATTRIB_TEX0 + unit]; 597 GLfloat (*targetcoords)[4] 598 = (GLfloat (*)[4]) 599 span->array->attribs[FRAG_ATTRIB_TEX0 + 600 ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0]; 601 602 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 603 const struct gl_texture_object *curObj = texUnit->_Current; 604 GLfloat *lambda = span->array->lambda[unit]; 605#if 0 606 GLchan (*texels)[4] = (GLchan (*)[4]) 607 (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan))); 608#else 609 float4_array texels = get_texel_array(swrast->TexelBuffer, unit, 610 span->end); 611#endif 612 GLuint i; 613 GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0]; 614 GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1]; 615 GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2]; 616 GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3]; 617 618 /* adjust texture lod (lambda) */ 619 if (span->arrayMask & SPAN_LAMBDA) { 620 if (texUnit->LodBias + curObj->LodBias != 0.0F) { 621 /* apply LOD bias, but don't clamp yet */ 622 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias, 623 -ctx->Const.MaxTextureLodBias, 624 ctx->Const.MaxTextureLodBias); 625 GLuint i; 626 for (i = 0; i < span->end; i++) { 627 lambda[i] += bias; 628 } 629 } 630 631 if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) { 632 /* apply LOD clamping to lambda */ 633 const GLfloat min = curObj->MinLod; 634 const GLfloat max = curObj->MaxLod; 635 GLuint i; 636 for (i = 0; i < span->end; i++) { 637 GLfloat l = lambda[i]; 638 lambda[i] = CLAMP(l, min, max); 639 } 640 } 641 } 642 643 /* Sample the texture (span->end = number of fragments) */ 644 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end, 645 texcoords, lambda, texels ); 646 647 /* manipulate the span values of the bump target 648 not sure this can work correctly even ignoring 649 the problem that channel is unsigned */ 650 for (i = 0; i < span->end; i++) { 651#if CHAN_TYPE == GL_FLOAT 652 targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] * 653 rotMatrix01) / targetcoords[i][3]; 654 targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] * 655 rotMatrix11) / targetcoords[i][3]; 656#else 657 targetcoords[i][0] += (CHAN_TO_FLOAT(texels[i][1]) * rotMatrix00 + 658 CHAN_TO_FLOAT(texels[i][1]) * rotMatrix01) / 659 targetcoords[i][3]; 660 targetcoords[i][1] += (CHAN_TO_FLOAT(texels[i][0]) * rotMatrix10 + 661 CHAN_TO_FLOAT(texels[i][1]) * rotMatrix11) / 662 targetcoords[i][3]; 663#endif 664 } 665 } 666 } 667 668 /* 669 * Must do all texture sampling before combining in order to 670 * accomodate GL_ARB_texture_env_crossbar. 671 */ 672 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 673 if (ctx->Texture.Unit[unit]._ReallyEnabled && 674 ctx->Texture.Unit[unit]._CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) { 675 const GLfloat (*texcoords)[4] = (const GLfloat (*)[4]) 676 span->array->attribs[FRAG_ATTRIB_TEX0 + unit]; 677 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; 678 const struct gl_texture_object *curObj = texUnit->_Current; 679 GLfloat *lambda = span->array->lambda[unit]; 680 float4_array texels = 681 get_texel_array(swrast->TexelBuffer, unit, span->end); 682 683 /* adjust texture lod (lambda) */ 684 if (span->arrayMask & SPAN_LAMBDA) { 685 if (texUnit->LodBias + curObj->LodBias != 0.0F) { 686 /* apply LOD bias, but don't clamp yet */ 687 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias, 688 -ctx->Const.MaxTextureLodBias, 689 ctx->Const.MaxTextureLodBias); 690 GLuint i; 691 for (i = 0; i < span->end; i++) { 692 lambda[i] += bias; 693 } 694 } 695 696 if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) { 697 /* apply LOD clamping to lambda */ 698 const GLfloat min = curObj->MinLod; 699 const GLfloat max = curObj->MaxLod; 700 GLuint i; 701 for (i = 0; i < span->end; i++) { 702 GLfloat l = lambda[i]; 703 lambda[i] = CLAMP(l, min, max); 704 } 705 } 706 } 707 708 /* Sample the texture (span->end = number of fragments) */ 709 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end, 710 texcoords, lambda, texels ); 711 712 /* GL_SGI_texture_color_table */ 713 if (texUnit->ColorTableEnabled) { 714 _mesa_lookup_rgba_float(&texUnit->ColorTable, span->end, texels); 715 } 716 717 /* GL_EXT_texture_swizzle */ 718 if (curObj->_Swizzle != SWIZZLE_NOOP) { 719 swizzle_texels(curObj->_Swizzle, span->end, texels); 720 } 721 } 722 } 723 724 /* 725 * OK, now apply the texture (aka texture combine/blend). 726 * We modify the span->color.rgba values. 727 */ 728 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 729 if (ctx->Texture.Unit[unit]._ReallyEnabled) { 730 texture_combine( ctx, unit, span->end, 731 primary_rgba, 732 swrast->TexelBuffer, 733 span->array->rgba ); 734 } 735 } 736} 737