1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 4 * All Rights Reserved. 5 * Copyright 2009 VMware, Inc. All Rights Reserved. 6 * Copyright © 2010-2011 Intel Corporation 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29 30#include "main/glheader.h" 31#include "main/context.h" 32 33#include "main/macros.h" 34#include "main/samplerobj.h" 35#include "main/shaderobj.h" 36#include "main/state.h" 37#include "main/texenvprogram.h" 38#include "main/texobj.h" 39#include "main/uniforms.h" 40#include "compiler/glsl/ir_builder.h" 41#include "compiler/glsl/ir_optimization.h" 42#include "compiler/glsl/glsl_parser_extras.h" 43#include "compiler/glsl/glsl_symbol_table.h" 44#include "compiler/glsl_types.h" 45#include "program/link_program.h" 46#include "program/program.h" 47#include "program/programopt.h" 48#include "program/prog_cache.h" 49#include "program/prog_instruction.h" 50#include "program/prog_parameter.h" 51#include "program/prog_print.h" 52#include "program/prog_statevars.h" 53#include "util/bitscan.h" 54 55using namespace ir_builder; 56 57/* 58 * Note on texture units: 59 * 60 * The number of texture units supported by fixed-function fragment 61 * processing is MAX_TEXTURE_COORD_UNITS, not MAX_TEXTURE_IMAGE_UNITS. 62 * That's because there's a one-to-one correspondence between texture 63 * coordinates and samplers in fixed-function processing. 64 * 65 * Since fixed-function vertex processing is limited to MAX_TEXTURE_COORD_UNITS 66 * sets of texcoords, so is fixed-function fragment processing. 67 * 68 * We can safely use ctx->Const.MaxTextureUnits for loop bounds. 69 */ 70 71 72static GLboolean 73texenv_doing_secondary_color(struct gl_context *ctx) 74{ 75 if (ctx->Light.Enabled && 76 (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) 77 return GL_TRUE; 78 79 if (ctx->Fog.ColorSumEnabled) 80 return GL_TRUE; 81 82 return GL_FALSE; 83} 84 85struct state_key { 86 GLuint nr_enabled_units:4; 87 GLuint separate_specular:1; 88 GLuint fog_mode:2; /**< FOG_x */ 89 GLuint inputs_available:12; 90 GLuint num_draw_buffers:4; 91 92 /* NOTE: This array of structs must be last! (see "keySize" below) */ 93 struct { 94 GLuint enabled:1; 95 GLuint source_index:4; /**< TEXTURE_x_INDEX */ 96 GLuint shadow:1; 97 98 /*** 99 * These are taken from struct gl_tex_env_combine_packed 100 * @{ 101 */ 102 GLuint ModeRGB:4; 103 GLuint ModeA:4; 104 GLuint ScaleShiftRGB:2; 105 GLuint ScaleShiftA:2; 106 GLuint NumArgsRGB:3; 107 GLuint NumArgsA:3; 108 struct gl_tex_env_argument ArgsRGB[MAX_COMBINER_TERMS]; 109 struct gl_tex_env_argument ArgsA[MAX_COMBINER_TERMS]; 110 /** @} */ 111 } unit[MAX_TEXTURE_COORD_UNITS]; 112}; 113 114 115/** 116 * Do we need to clamp the results of the given texture env/combine mode? 117 * If the inputs to the mode are in [0,1] we don't always have to clamp 118 * the results. 119 */ 120static GLboolean 121need_saturate( GLuint mode ) 122{ 123 switch (mode) { 124 case TEXENV_MODE_REPLACE: 125 case TEXENV_MODE_MODULATE: 126 case TEXENV_MODE_INTERPOLATE: 127 return GL_FALSE; 128 case TEXENV_MODE_ADD: 129 case TEXENV_MODE_ADD_SIGNED: 130 case TEXENV_MODE_SUBTRACT: 131 case TEXENV_MODE_DOT3_RGB: 132 case TEXENV_MODE_DOT3_RGB_EXT: 133 case TEXENV_MODE_DOT3_RGBA: 134 case TEXENV_MODE_DOT3_RGBA_EXT: 135 case TEXENV_MODE_MODULATE_ADD_ATI: 136 case TEXENV_MODE_MODULATE_SIGNED_ADD_ATI: 137 case TEXENV_MODE_MODULATE_SUBTRACT_ATI: 138 case TEXENV_MODE_ADD_PRODUCTS_NV: 139 case TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV: 140 return GL_TRUE; 141 default: 142 assert(0); 143 return GL_FALSE; 144 } 145} 146 147#define VERT_BIT_TEX_ANY (0xff << VERT_ATTRIB_TEX0) 148 149/** 150 * Identify all possible varying inputs. The fragment program will 151 * never reference non-varying inputs, but will track them via state 152 * constants instead. 153 * 154 * This function figures out all the inputs that the fragment program 155 * has access to and filters input bitmask. 156 */ 157static GLbitfield filter_fp_input_mask( GLbitfield fp_inputs, 158 struct gl_context *ctx ) 159{ 160 if (ctx->VertexProgram._Overriden) { 161 /* Somebody's messing with the vertex program and we don't have 162 * a clue what's happening. Assume that it could be producing 163 * all possible outputs. 164 */ 165 return fp_inputs; 166 } 167 168 if (ctx->RenderMode == GL_FEEDBACK) { 169 /* _NEW_RENDERMODE */ 170 return fp_inputs & (VARYING_BIT_COL0 | VARYING_BIT_TEX0); 171 } 172 173 /* _NEW_PROGRAM */ 174 const GLboolean vertexShader = 175 ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] != NULL; 176 const GLboolean vertexProgram = _mesa_arb_vertex_program_enabled(ctx); 177 178 if (!(vertexProgram || vertexShader)) { 179 /* Fixed function vertex logic */ 180 GLbitfield possible_inputs = 0; 181 182 GLbitfield varying_inputs = ctx->VertexProgram._VaryingInputs; 183 /* We only update ctx->VertexProgram._VaryingInputs when in VP_MODE_FF _VPMode */ 184 assert(VP_MODE_FF == ctx->VertexProgram._VPMode); 185 186 /* These get generated in the setup routine regardless of the 187 * vertex program: 188 */ 189 /* _NEW_POINT */ 190 if (ctx->Point.PointSprite) { 191 /* All texture varyings are possible to use */ 192 possible_inputs = VARYING_BITS_TEX_ANY; 193 } 194 else { 195 const GLbitfield possible_tex_inputs = 196 ctx->Texture._TexGenEnabled | 197 ctx->Texture._TexMatEnabled | 198 ((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0); 199 200 possible_inputs = (possible_tex_inputs << VARYING_SLOT_TEX0); 201 } 202 203 /* First look at what values may be computed by the generated 204 * vertex program: 205 */ 206 if (ctx->Light.Enabled) { 207 possible_inputs |= VARYING_BIT_COL0; 208 209 if (texenv_doing_secondary_color(ctx)) 210 possible_inputs |= VARYING_BIT_COL1; 211 } 212 213 /* Then look at what might be varying as a result of enabled 214 * arrays, etc: 215 */ 216 if (varying_inputs & VERT_BIT_COLOR0) 217 possible_inputs |= VARYING_BIT_COL0; 218 if (varying_inputs & VERT_BIT_COLOR1) 219 possible_inputs |= VARYING_BIT_COL1; 220 221 return fp_inputs & possible_inputs; 222 } 223 224 /* calculate from vp->outputs */ 225 struct gl_program *vprog; 226 227 /* Choose GLSL vertex shader over ARB vertex program. Need this 228 * since vertex shader state validation comes after fragment state 229 * validation (see additional comments in state.c). 230 */ 231 if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY] != NULL) 232 vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]; 233 else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] != NULL) 234 vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; 235 else if (vertexShader) 236 vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]; 237 else 238 vprog = ctx->VertexProgram.Current; 239 240 GLbitfield possible_inputs = vprog->info.outputs_written; 241 242 /* These get generated in the setup routine regardless of the 243 * vertex program: 244 */ 245 /* _NEW_POINT */ 246 if (ctx->Point.PointSprite) { 247 /* All texture varyings are possible to use */ 248 possible_inputs |= VARYING_BITS_TEX_ANY; 249 } 250 251 return fp_inputs & possible_inputs; 252} 253 254 255/** 256 * Examine current texture environment state and generate a unique 257 * key to identify it. 258 */ 259static GLuint make_state_key( struct gl_context *ctx, struct state_key *key ) 260{ 261 GLbitfield inputs_referenced = VARYING_BIT_COL0; 262 GLbitfield mask; 263 GLuint keySize; 264 265 memset(key, 0, sizeof(*key)); 266 267 /* _NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE */ 268 mask = ctx->Texture._EnabledCoordUnits; 269 int i = -1; 270 while (mask) { 271 i = u_bit_scan(&mask); 272 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; 273 const struct gl_texture_object *texObj = texUnit->_Current; 274 const struct gl_tex_env_combine_packed *comb = 275 &ctx->Texture.FixedFuncUnit[i]._CurrentCombinePacked; 276 277 if (!texObj) 278 continue; 279 280 key->unit[i].enabled = 1; 281 inputs_referenced |= VARYING_BIT_TEX(i); 282 283 key->unit[i].source_index = texObj->TargetIndex; 284 285 const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, i); 286 if (samp->Attrib.CompareMode == GL_COMPARE_R_TO_TEXTURE) { 287 const GLenum format = _mesa_texture_base_format(texObj); 288 key->unit[i].shadow = (format == GL_DEPTH_COMPONENT || 289 format == GL_DEPTH_STENCIL_EXT); 290 } 291 292 key->unit[i].ModeRGB = comb->ModeRGB; 293 key->unit[i].ModeA = comb->ModeA; 294 key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB; 295 key->unit[i].ScaleShiftA = comb->ScaleShiftA; 296 key->unit[i].NumArgsRGB = comb->NumArgsRGB; 297 key->unit[i].NumArgsA = comb->NumArgsA; 298 299 memcpy(key->unit[i].ArgsRGB, comb->ArgsRGB, sizeof comb->ArgsRGB); 300 memcpy(key->unit[i].ArgsA, comb->ArgsA, sizeof comb->ArgsA); 301 } 302 303 key->nr_enabled_units = i + 1; 304 305 /* _NEW_FOG */ 306 if (texenv_doing_secondary_color(ctx)) { 307 key->separate_specular = 1; 308 inputs_referenced |= VARYING_BIT_COL1; 309 } 310 311 /* _NEW_FOG */ 312 key->fog_mode = ctx->Fog._PackedEnabledMode; 313 314 /* _NEW_BUFFERS */ 315 key->num_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers; 316 317 /* _NEW_COLOR */ 318 if (ctx->Color.AlphaEnabled && key->num_draw_buffers == 0) { 319 /* if alpha test is enabled we need to emit at least one color */ 320 key->num_draw_buffers = 1; 321 } 322 323 key->inputs_available = filter_fp_input_mask(inputs_referenced, ctx); 324 325 /* compute size of state key, ignoring unused texture units */ 326 keySize = sizeof(*key) - sizeof(key->unit) 327 + key->nr_enabled_units * sizeof(key->unit[0]); 328 329 return keySize; 330} 331 332 333/** State used to build the fragment program: 334 */ 335class texenv_fragment_program : public ir_factory { 336public: 337 struct gl_shader_program *shader_program; 338 struct gl_shader *shader; 339 exec_list *top_instructions; 340 struct state_key *state; 341 342 ir_variable *src_texture[MAX_TEXTURE_COORD_UNITS]; 343 /* Reg containing each texture unit's sampled texture color, 344 * else undef. 345 */ 346 347 ir_rvalue *src_previous; /**< Reg containing color from previous 348 * stage. May need to be decl'd. 349 */ 350}; 351 352static ir_rvalue * 353get_current_attrib(texenv_fragment_program *p, GLuint attrib) 354{ 355 ir_variable *current; 356 char name[128]; 357 358 snprintf(name, sizeof(name), "gl_CurrentAttribFrag%uMESA", attrib); 359 360 current = p->shader->symbols->get_variable(name); 361 assert(current); 362 return new(p->mem_ctx) ir_dereference_variable(current); 363} 364 365static ir_rvalue * 366get_gl_Color(texenv_fragment_program *p) 367{ 368 if (p->state->inputs_available & VARYING_BIT_COL0) { 369 ir_variable *var = p->shader->symbols->get_variable("gl_Color"); 370 assert(var); 371 return new(p->mem_ctx) ir_dereference_variable(var); 372 } else { 373 return get_current_attrib(p, VERT_ATTRIB_COLOR0); 374 } 375} 376 377static ir_rvalue * 378get_source(texenv_fragment_program *p, 379 GLuint src, GLuint unit) 380{ 381 ir_variable *var; 382 ir_dereference *deref; 383 384 switch (src) { 385 case TEXENV_SRC_TEXTURE: 386 return new(p->mem_ctx) ir_dereference_variable(p->src_texture[unit]); 387 388 case TEXENV_SRC_TEXTURE0: 389 case TEXENV_SRC_TEXTURE1: 390 case TEXENV_SRC_TEXTURE2: 391 case TEXENV_SRC_TEXTURE3: 392 case TEXENV_SRC_TEXTURE4: 393 case TEXENV_SRC_TEXTURE5: 394 case TEXENV_SRC_TEXTURE6: 395 case TEXENV_SRC_TEXTURE7: 396 return new(p->mem_ctx) 397 ir_dereference_variable(p->src_texture[src - TEXENV_SRC_TEXTURE0]); 398 399 case TEXENV_SRC_CONSTANT: 400 var = p->shader->symbols->get_variable("gl_TextureEnvColor"); 401 assert(var); 402 deref = new(p->mem_ctx) ir_dereference_variable(var); 403 var->data.max_array_access = MAX2(var->data.max_array_access, (int)unit); 404 return new(p->mem_ctx) ir_dereference_array(deref, 405 new(p->mem_ctx) ir_constant(unit)); 406 407 case TEXENV_SRC_PRIMARY_COLOR: 408 var = p->shader->symbols->get_variable("gl_Color"); 409 assert(var); 410 return new(p->mem_ctx) ir_dereference_variable(var); 411 412 case TEXENV_SRC_ZERO: 413 return new(p->mem_ctx) ir_constant(0.0f); 414 415 case TEXENV_SRC_ONE: 416 return new(p->mem_ctx) ir_constant(1.0f); 417 418 case TEXENV_SRC_PREVIOUS: 419 if (!p->src_previous) { 420 return get_gl_Color(p); 421 } else { 422 return p->src_previous->clone(p->mem_ctx, NULL); 423 } 424 425 default: 426 assert(0); 427 return NULL; 428 } 429} 430 431static ir_rvalue * 432emit_combine_source(texenv_fragment_program *p, 433 GLuint unit, 434 GLuint source, 435 GLuint operand) 436{ 437 ir_rvalue *src; 438 439 src = get_source(p, source, unit); 440 441 switch (operand) { 442 case TEXENV_OPR_ONE_MINUS_COLOR: 443 return sub(new(p->mem_ctx) ir_constant(1.0f), src); 444 445 case TEXENV_OPR_ALPHA: 446 return src->type->is_scalar() ? src : swizzle_w(src); 447 448 case TEXENV_OPR_ONE_MINUS_ALPHA: { 449 ir_rvalue *const scalar = src->type->is_scalar() ? src : swizzle_w(src); 450 451 return sub(new(p->mem_ctx) ir_constant(1.0f), scalar); 452 } 453 454 case TEXENV_OPR_COLOR: 455 return src; 456 457 default: 458 assert(0); 459 return src; 460 } 461} 462 463/** 464 * Check if the RGB and Alpha sources and operands match for the given 465 * texture unit's combinder state. When the RGB and A sources and 466 * operands match, we can emit fewer instructions. 467 */ 468static GLboolean args_match( const struct state_key *key, GLuint unit ) 469{ 470 GLuint i, numArgs = key->unit[unit].NumArgsRGB; 471 472 for (i = 0; i < numArgs; i++) { 473 if (key->unit[unit].ArgsA[i].Source != key->unit[unit].ArgsRGB[i].Source) 474 return GL_FALSE; 475 476 switch (key->unit[unit].ArgsA[i].Operand) { 477 case TEXENV_OPR_ALPHA: 478 switch (key->unit[unit].ArgsRGB[i].Operand) { 479 case TEXENV_OPR_COLOR: 480 case TEXENV_OPR_ALPHA: 481 break; 482 default: 483 return GL_FALSE; 484 } 485 break; 486 case TEXENV_OPR_ONE_MINUS_ALPHA: 487 switch (key->unit[unit].ArgsRGB[i].Operand) { 488 case TEXENV_OPR_ONE_MINUS_COLOR: 489 case TEXENV_OPR_ONE_MINUS_ALPHA: 490 break; 491 default: 492 return GL_FALSE; 493 } 494 break; 495 default: 496 return GL_FALSE; /* impossible */ 497 } 498 } 499 500 return GL_TRUE; 501} 502 503static ir_rvalue * 504smear(ir_rvalue *val) 505{ 506 if (!val->type->is_scalar()) 507 return val; 508 509 return swizzle_xxxx(val); 510} 511 512static ir_rvalue * 513emit_combine(texenv_fragment_program *p, 514 GLuint unit, 515 GLuint nr, 516 GLuint mode, 517 const struct gl_tex_env_argument *opt) 518{ 519 ir_rvalue *src[MAX_COMBINER_TERMS]; 520 ir_rvalue *tmp0, *tmp1; 521 GLuint i; 522 523 assert(nr <= MAX_COMBINER_TERMS); 524 525 for (i = 0; i < nr; i++) 526 src[i] = emit_combine_source( p, unit, opt[i].Source, opt[i].Operand ); 527 528 switch (mode) { 529 case TEXENV_MODE_REPLACE: 530 return src[0]; 531 532 case TEXENV_MODE_MODULATE: 533 return mul(src[0], src[1]); 534 535 case TEXENV_MODE_ADD: 536 return add(src[0], src[1]); 537 538 case TEXENV_MODE_ADD_SIGNED: 539 return add(add(src[0], src[1]), new(p->mem_ctx) ir_constant(-0.5f)); 540 541 case TEXENV_MODE_INTERPOLATE: 542 /* Arg0 * (Arg2) + Arg1 * (1-Arg2) */ 543 tmp0 = mul(src[0], src[2]); 544 tmp1 = mul(src[1], sub(new(p->mem_ctx) ir_constant(1.0f), 545 src[2]->clone(p->mem_ctx, NULL))); 546 return add(tmp0, tmp1); 547 548 case TEXENV_MODE_SUBTRACT: 549 return sub(src[0], src[1]); 550 551 case TEXENV_MODE_DOT3_RGBA: 552 case TEXENV_MODE_DOT3_RGBA_EXT: 553 case TEXENV_MODE_DOT3_RGB_EXT: 554 case TEXENV_MODE_DOT3_RGB: { 555 tmp0 = mul(src[0], new(p->mem_ctx) ir_constant(2.0f)); 556 tmp0 = add(tmp0, new(p->mem_ctx) ir_constant(-1.0f)); 557 558 tmp1 = mul(src[1], new(p->mem_ctx) ir_constant(2.0f)); 559 tmp1 = add(tmp1, new(p->mem_ctx) ir_constant(-1.0f)); 560 561 return dot(swizzle_xyz(smear(tmp0)), swizzle_xyz(smear(tmp1))); 562 } 563 case TEXENV_MODE_MODULATE_ADD_ATI: 564 return add(mul(src[0], src[2]), src[1]); 565 566 case TEXENV_MODE_MODULATE_SIGNED_ADD_ATI: 567 return add(add(mul(src[0], src[2]), src[1]), 568 new(p->mem_ctx) ir_constant(-0.5f)); 569 570 case TEXENV_MODE_MODULATE_SUBTRACT_ATI: 571 return sub(mul(src[0], src[2]), src[1]); 572 573 case TEXENV_MODE_ADD_PRODUCTS_NV: 574 return add(mul(src[0], src[1]), mul(src[2], src[3])); 575 576 case TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV: 577 return add(add(mul(src[0], src[1]), mul(src[2], src[3])), 578 new(p->mem_ctx) ir_constant(-0.5f)); 579 default: 580 assert(0); 581 return src[0]; 582 } 583} 584 585/** 586 * Generate instructions for one texture unit's env/combiner mode. 587 */ 588static ir_rvalue * 589emit_texenv(texenv_fragment_program *p, GLuint unit) 590{ 591 const struct state_key *key = p->state; 592 GLboolean rgb_saturate, alpha_saturate; 593 GLuint rgb_shift, alpha_shift; 594 595 if (!key->unit[unit].enabled) { 596 return get_source(p, TEXENV_SRC_PREVIOUS, 0); 597 } 598 599 switch (key->unit[unit].ModeRGB) { 600 case TEXENV_MODE_DOT3_RGB_EXT: 601 alpha_shift = key->unit[unit].ScaleShiftA; 602 rgb_shift = 0; 603 break; 604 case TEXENV_MODE_DOT3_RGBA_EXT: 605 alpha_shift = 0; 606 rgb_shift = 0; 607 break; 608 default: 609 rgb_shift = key->unit[unit].ScaleShiftRGB; 610 alpha_shift = key->unit[unit].ScaleShiftA; 611 break; 612 } 613 614 /* If we'll do rgb/alpha shifting don't saturate in emit_combine(). 615 * We don't want to clamp twice. 616 */ 617 if (rgb_shift) 618 rgb_saturate = GL_FALSE; /* saturate after rgb shift */ 619 else if (need_saturate(key->unit[unit].ModeRGB)) 620 rgb_saturate = GL_TRUE; 621 else 622 rgb_saturate = GL_FALSE; 623 624 if (alpha_shift) 625 alpha_saturate = GL_FALSE; /* saturate after alpha shift */ 626 else if (need_saturate(key->unit[unit].ModeA)) 627 alpha_saturate = GL_TRUE; 628 else 629 alpha_saturate = GL_FALSE; 630 631 ir_variable *temp_var = p->make_temp(glsl_type::vec4_type, "texenv_combine"); 632 ir_dereference *deref; 633 ir_rvalue *val; 634 635 /* Emit the RGB and A combine ops 636 */ 637 if (key->unit[unit].ModeRGB == key->unit[unit].ModeA && 638 args_match(key, unit)) { 639 val = emit_combine(p, unit, 640 key->unit[unit].NumArgsRGB, 641 key->unit[unit].ModeRGB, 642 key->unit[unit].ArgsRGB); 643 val = smear(val); 644 if (rgb_saturate) 645 val = saturate(val); 646 647 p->emit(assign(temp_var, val)); 648 } 649 else if (key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA_EXT || 650 key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA) { 651 ir_rvalue *val = emit_combine(p, unit, 652 key->unit[unit].NumArgsRGB, 653 key->unit[unit].ModeRGB, 654 key->unit[unit].ArgsRGB); 655 val = smear(val); 656 if (rgb_saturate) 657 val = saturate(val); 658 p->emit(assign(temp_var, val)); 659 } 660 else { 661 /* Need to do something to stop from re-emitting identical 662 * argument calculations here: 663 */ 664 val = emit_combine(p, unit, 665 key->unit[unit].NumArgsRGB, 666 key->unit[unit].ModeRGB, 667 key->unit[unit].ArgsRGB); 668 val = swizzle_xyz(smear(val)); 669 if (rgb_saturate) 670 val = saturate(val); 671 p->emit(assign(temp_var, val, WRITEMASK_XYZ)); 672 673 val = emit_combine(p, unit, 674 key->unit[unit].NumArgsA, 675 key->unit[unit].ModeA, 676 key->unit[unit].ArgsA); 677 val = swizzle_w(smear(val)); 678 if (alpha_saturate) 679 val = saturate(val); 680 p->emit(assign(temp_var, val, WRITEMASK_W)); 681 } 682 683 deref = new(p->mem_ctx) ir_dereference_variable(temp_var); 684 685 /* Deal with the final shift: 686 */ 687 if (alpha_shift || rgb_shift) { 688 ir_constant *shift; 689 690 if (rgb_shift == alpha_shift) { 691 shift = new(p->mem_ctx) ir_constant((float)(1 << rgb_shift)); 692 } 693 else { 694 ir_constant_data const_data; 695 696 const_data.f[0] = float(1 << rgb_shift); 697 const_data.f[1] = float(1 << rgb_shift); 698 const_data.f[2] = float(1 << rgb_shift); 699 const_data.f[3] = float(1 << alpha_shift); 700 701 shift = new(p->mem_ctx) ir_constant(glsl_type::vec4_type, 702 &const_data); 703 } 704 705 return saturate(mul(deref, shift)); 706 } 707 else 708 return deref; 709} 710 711 712/** 713 * Generate instruction for getting a texture source term. 714 */ 715static void load_texture( texenv_fragment_program *p, GLuint unit ) 716{ 717 ir_dereference *deref; 718 719 if (p->src_texture[unit]) 720 return; 721 722 const GLuint texTarget = p->state->unit[unit].source_index; 723 ir_rvalue *texcoord; 724 725 if (!(p->state->inputs_available & (VARYING_BIT_TEX0 << unit))) { 726 texcoord = get_current_attrib(p, VERT_ATTRIB_TEX0 + unit); 727 } else { 728 ir_variable *tc_array = p->shader->symbols->get_variable("gl_TexCoord"); 729 assert(tc_array); 730 texcoord = new(p->mem_ctx) ir_dereference_variable(tc_array); 731 ir_rvalue *index = new(p->mem_ctx) ir_constant(unit); 732 texcoord = new(p->mem_ctx) ir_dereference_array(texcoord, index); 733 tc_array->data.max_array_access = MAX2(tc_array->data.max_array_access, (int)unit); 734 } 735 736 if (!p->state->unit[unit].enabled) { 737 p->src_texture[unit] = p->make_temp(glsl_type::vec4_type, 738 "dummy_tex"); 739 p->emit(p->src_texture[unit]); 740 741 p->emit(assign(p->src_texture[unit], new(p->mem_ctx) ir_constant(0.0f))); 742 return ; 743 } 744 745 const glsl_type *sampler_type = NULL; 746 int coords = 0; 747 748 switch (texTarget) { 749 case TEXTURE_1D_INDEX: 750 if (p->state->unit[unit].shadow) 751 sampler_type = glsl_type::sampler1DShadow_type; 752 else 753 sampler_type = glsl_type::sampler1D_type; 754 coords = 1; 755 break; 756 case TEXTURE_1D_ARRAY_INDEX: 757 if (p->state->unit[unit].shadow) 758 sampler_type = glsl_type::sampler1DArrayShadow_type; 759 else 760 sampler_type = glsl_type::sampler1DArray_type; 761 coords = 2; 762 break; 763 case TEXTURE_2D_INDEX: 764 if (p->state->unit[unit].shadow) 765 sampler_type = glsl_type::sampler2DShadow_type; 766 else 767 sampler_type = glsl_type::sampler2D_type; 768 coords = 2; 769 break; 770 case TEXTURE_2D_ARRAY_INDEX: 771 if (p->state->unit[unit].shadow) 772 sampler_type = glsl_type::sampler2DArrayShadow_type; 773 else 774 sampler_type = glsl_type::sampler2DArray_type; 775 coords = 3; 776 break; 777 case TEXTURE_RECT_INDEX: 778 if (p->state->unit[unit].shadow) 779 sampler_type = glsl_type::sampler2DRectShadow_type; 780 else 781 sampler_type = glsl_type::sampler2DRect_type; 782 coords = 2; 783 break; 784 case TEXTURE_3D_INDEX: 785 assert(!p->state->unit[unit].shadow); 786 sampler_type = glsl_type::sampler3D_type; 787 coords = 3; 788 break; 789 case TEXTURE_CUBE_INDEX: 790 if (p->state->unit[unit].shadow) 791 sampler_type = glsl_type::samplerCubeShadow_type; 792 else 793 sampler_type = glsl_type::samplerCube_type; 794 coords = 3; 795 break; 796 case TEXTURE_EXTERNAL_INDEX: 797 assert(!p->state->unit[unit].shadow); 798 sampler_type = glsl_type::samplerExternalOES_type; 799 coords = 2; 800 break; 801 } 802 803 p->src_texture[unit] = p->make_temp(glsl_type::vec4_type, 804 "tex"); 805 806 ir_texture *tex = new(p->mem_ctx) ir_texture(ir_tex); 807 808 809 char *sampler_name = ralloc_asprintf(p->mem_ctx, "sampler_%d", unit); 810 ir_variable *sampler = new(p->mem_ctx) ir_variable(sampler_type, 811 sampler_name, 812 ir_var_uniform); 813 p->top_instructions->push_head(sampler); 814 815 /* Set the texture unit for this sampler in the same way that 816 * layout(binding=X) would. 817 */ 818 sampler->data.explicit_binding = true; 819 sampler->data.binding = unit; 820 821 deref = new(p->mem_ctx) ir_dereference_variable(sampler); 822 tex->set_sampler(deref, glsl_type::vec4_type); 823 824 tex->coordinate = new(p->mem_ctx) ir_swizzle(texcoord, 0, 1, 2, 3, coords); 825 826 if (p->state->unit[unit].shadow) { 827 texcoord = texcoord->clone(p->mem_ctx, NULL); 828 tex->shadow_comparator = new(p->mem_ctx) ir_swizzle(texcoord, 829 coords, 0, 0, 0, 830 1); 831 coords++; 832 } 833 834 texcoord = texcoord->clone(p->mem_ctx, NULL); 835 tex->projector = swizzle_w(texcoord); 836 837 p->emit(assign(p->src_texture[unit], tex)); 838} 839 840static void 841load_texenv_source(texenv_fragment_program *p, 842 GLuint src, GLuint unit) 843{ 844 switch (src) { 845 case TEXENV_SRC_TEXTURE: 846 load_texture(p, unit); 847 break; 848 849 case TEXENV_SRC_TEXTURE0: 850 case TEXENV_SRC_TEXTURE1: 851 case TEXENV_SRC_TEXTURE2: 852 case TEXENV_SRC_TEXTURE3: 853 case TEXENV_SRC_TEXTURE4: 854 case TEXENV_SRC_TEXTURE5: 855 case TEXENV_SRC_TEXTURE6: 856 case TEXENV_SRC_TEXTURE7: 857 load_texture(p, src - TEXENV_SRC_TEXTURE0); 858 break; 859 860 default: 861 /* not a texture src - do nothing */ 862 break; 863 } 864} 865 866 867/** 868 * Generate instructions for loading all texture source terms. 869 */ 870static GLboolean 871load_texunit_sources( texenv_fragment_program *p, GLuint unit ) 872{ 873 const struct state_key *key = p->state; 874 GLuint i; 875 876 for (i = 0; i < key->unit[unit].NumArgsRGB; i++) { 877 load_texenv_source( p, key->unit[unit].ArgsRGB[i].Source, unit ); 878 } 879 880 for (i = 0; i < key->unit[unit].NumArgsA; i++) { 881 load_texenv_source( p, key->unit[unit].ArgsA[i].Source, unit ); 882 } 883 884 return GL_TRUE; 885} 886 887/** 888 * Applies the fog calculations. 889 * 890 * This is basically like the ARB_fragment_prorgam fog options. Note 891 * that ffvertex_prog.c produces fogcoord for us when 892 * GL_FOG_COORDINATE_EXT is set to GL_FRAGMENT_DEPTH_EXT. 893 */ 894static ir_rvalue * 895emit_fog_instructions(texenv_fragment_program *p, 896 ir_rvalue *fragcolor) 897{ 898 struct state_key *key = p->state; 899 ir_rvalue *f, *temp; 900 ir_variable *params, *oparams; 901 ir_variable *fogcoord; 902 903 /* Temporary storage for the whole fog result. Fog calculations 904 * only affect rgb so we're hanging on to the .a value of fragcolor 905 * this way. 906 */ 907 ir_variable *fog_result = p->make_temp(glsl_type::vec4_type, "fog_result"); 908 p->emit(assign(fog_result, fragcolor)); 909 910 fragcolor = swizzle_xyz(fog_result); 911 912 oparams = p->shader->symbols->get_variable("gl_FogParamsOptimizedMESA"); 913 assert(oparams); 914 fogcoord = p->shader->symbols->get_variable("gl_FogFragCoord"); 915 assert(fogcoord); 916 params = p->shader->symbols->get_variable("gl_Fog"); 917 assert(params); 918 f = new(p->mem_ctx) ir_dereference_variable(fogcoord); 919 920 ir_variable *f_var = p->make_temp(glsl_type::float_type, "fog_factor"); 921 922 switch (key->fog_mode) { 923 case FOG_LINEAR: 924 /* f = (end - z) / (end - start) 925 * 926 * gl_MesaFogParamsOptimized gives us (-1 / (end - start)) and 927 * (end / (end - start)) so we can generate a single MAD. 928 */ 929 f = add(mul(f, swizzle_x(oparams)), swizzle_y(oparams)); 930 break; 931 case FOG_EXP: 932 /* f = e^(-(density * fogcoord)) 933 * 934 * gl_MesaFogParamsOptimized gives us density/ln(2) so we can 935 * use EXP2 which is generally the native instruction without 936 * having to do any further math on the fog density uniform. 937 */ 938 f = mul(f, swizzle_z(oparams)); 939 f = new(p->mem_ctx) ir_expression(ir_unop_neg, f); 940 f = new(p->mem_ctx) ir_expression(ir_unop_exp2, f); 941 break; 942 case FOG_EXP2: 943 /* f = e^(-(density * fogcoord)^2) 944 * 945 * gl_MesaFogParamsOptimized gives us density/sqrt(ln(2)) so we 946 * can do this like FOG_EXP but with a squaring after the 947 * multiply by density. 948 */ 949 ir_variable *temp_var = p->make_temp(glsl_type::float_type, "fog_temp"); 950 p->emit(assign(temp_var, mul(f, swizzle_w(oparams)))); 951 952 f = mul(temp_var, temp_var); 953 f = new(p->mem_ctx) ir_expression(ir_unop_neg, f); 954 f = new(p->mem_ctx) ir_expression(ir_unop_exp2, f); 955 break; 956 } 957 958 p->emit(assign(f_var, saturate(f))); 959 960 f = sub(new(p->mem_ctx) ir_constant(1.0f), f_var); 961 temp = new(p->mem_ctx) ir_dereference_variable(params); 962 temp = new(p->mem_ctx) ir_dereference_record(temp, "color"); 963 temp = mul(swizzle_xyz(temp), f); 964 965 p->emit(assign(fog_result, add(temp, mul(fragcolor, f_var)), WRITEMASK_XYZ)); 966 967 return new(p->mem_ctx) ir_dereference_variable(fog_result); 968} 969 970static void 971emit_instructions(texenv_fragment_program *p) 972{ 973 struct state_key *key = p->state; 974 GLuint unit; 975 976 if (key->nr_enabled_units) { 977 /* First pass - to support texture_env_crossbar, first identify 978 * all referenced texture sources and emit texld instructions 979 * for each: 980 */ 981 for (unit = 0; unit < key->nr_enabled_units; unit++) 982 if (key->unit[unit].enabled) { 983 load_texunit_sources(p, unit); 984 } 985 986 /* Second pass - emit combine instructions to build final color: 987 */ 988 for (unit = 0; unit < key->nr_enabled_units; unit++) { 989 if (key->unit[unit].enabled) { 990 p->src_previous = emit_texenv(p, unit); 991 } 992 } 993 } 994 995 ir_rvalue *cf = get_source(p, TEXENV_SRC_PREVIOUS, 0); 996 997 if (key->separate_specular) { 998 ir_variable *spec_result = p->make_temp(glsl_type::vec4_type, 999 "specular_add"); 1000 p->emit(assign(spec_result, cf)); 1001 1002 ir_rvalue *secondary; 1003 if (p->state->inputs_available & VARYING_BIT_COL1) { 1004 ir_variable *var = 1005 p->shader->symbols->get_variable("gl_SecondaryColor"); 1006 assert(var); 1007 secondary = swizzle_xyz(var); 1008 } else { 1009 secondary = swizzle_xyz(get_current_attrib(p, VERT_ATTRIB_COLOR1)); 1010 } 1011 1012 p->emit(assign(spec_result, add(swizzle_xyz(spec_result), secondary), 1013 WRITEMASK_XYZ)); 1014 1015 cf = new(p->mem_ctx) ir_dereference_variable(spec_result); 1016 } 1017 1018 if (key->fog_mode) { 1019 cf = emit_fog_instructions(p, cf); 1020 } 1021 1022 ir_variable *frag_color = p->shader->symbols->get_variable("gl_FragColor"); 1023 assert(frag_color); 1024 p->emit(assign(frag_color, cf)); 1025} 1026 1027/** 1028 * Generate a new fragment program which implements the context's 1029 * current texture env/combine mode. 1030 */ 1031static struct gl_shader_program * 1032create_new_program(struct gl_context *ctx, struct state_key *key) 1033{ 1034 texenv_fragment_program p; 1035 unsigned int unit; 1036 _mesa_glsl_parse_state *state; 1037 1038 p.mem_ctx = ralloc_context(NULL); 1039 p.shader = _mesa_new_shader(0, MESA_SHADER_FRAGMENT); 1040 p.shader->ir = new(p.shader) exec_list; 1041 state = new(p.shader) _mesa_glsl_parse_state(ctx, MESA_SHADER_FRAGMENT, 1042 p.shader); 1043 p.shader->symbols = state->symbols; 1044 p.top_instructions = p.shader->ir; 1045 p.instructions = p.shader->ir; 1046 p.state = key; 1047 p.shader_program = _mesa_new_shader_program(0); 1048 1049 /* Tell the linker to ignore the fact that we're building a 1050 * separate shader, in case we're in a GLES2 context that would 1051 * normally reject that. The real problem is that we're building a 1052 * fixed function program in a GLES2 context at all, but that's a 1053 * big mess to clean up. 1054 */ 1055 p.shader_program->SeparateShader = GL_TRUE; 1056 1057 /* The legacy GLSL shadow functions follow the depth texture 1058 * mode and return vec4. The GLSL 1.30 shadow functions return float and 1059 * ignore the depth texture mode. That's a shader and state dependency 1060 * that's difficult to deal with. st/mesa uses a simple but not 1061 * completely correct solution: if the shader declares GLSL >= 1.30 and 1062 * the depth texture mode is GL_ALPHA (000X), it sets the XXXX swizzle 1063 * instead. Thus, the GLSL 1.30 shadow function will get the result in .x 1064 * and legacy shadow functions will get it in .w as expected. 1065 * For the fixed-function fragment shader, use 120 to get correct behavior 1066 * for GL_ALPHA. 1067 */ 1068 state->language_version = 120; 1069 1070 state->es_shader = false; 1071 if (_mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external) 1072 state->OES_EGL_image_external_enable = true; 1073 _mesa_glsl_initialize_types(state); 1074 _mesa_glsl_initialize_variables(p.instructions, state); 1075 1076 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) 1077 p.src_texture[unit] = NULL; 1078 1079 p.src_previous = NULL; 1080 1081 ir_function *main_f = new(p.mem_ctx) ir_function("main"); 1082 p.emit(main_f); 1083 state->symbols->add_function(main_f); 1084 1085 ir_function_signature *main_sig = 1086 new(p.mem_ctx) ir_function_signature(glsl_type::void_type); 1087 main_sig->is_defined = true; 1088 main_f->add_signature(main_sig); 1089 1090 p.instructions = &main_sig->body; 1091 if (key->num_draw_buffers) 1092 emit_instructions(&p); 1093 1094 validate_ir_tree(p.shader->ir); 1095 1096 reparent_ir(p.shader->ir, p.shader->ir); 1097 1098 p.shader->CompileStatus = COMPILE_SUCCESS; 1099 p.shader->Version = state->language_version; 1100 p.shader_program->Shaders = 1101 (gl_shader **)malloc(sizeof(*p.shader_program->Shaders)); 1102 p.shader_program->Shaders[0] = p.shader; 1103 p.shader_program->NumShaders = 1; 1104 1105 _mesa_glsl_link_shader(ctx, p.shader_program); 1106 1107 if (!p.shader_program->data->LinkStatus) 1108 _mesa_problem(ctx, "Failed to link fixed function fragment shader: %s\n", 1109 p.shader_program->data->InfoLog); 1110 1111 ralloc_free(p.mem_ctx); 1112 return p.shader_program; 1113} 1114 1115extern "C" { 1116 1117/** 1118 * Return a fragment program which implements the current 1119 * fixed-function texture, fog and color-sum operations. 1120 */ 1121struct gl_shader_program * 1122_mesa_get_fixed_func_fragment_program(struct gl_context *ctx) 1123{ 1124 struct gl_shader_program *shader_program; 1125 struct state_key key; 1126 GLuint keySize; 1127 1128 keySize = make_state_key(ctx, &key); 1129 1130 shader_program = (struct gl_shader_program *) 1131 _mesa_search_program_cache(ctx->FragmentProgram.Cache, 1132 &key, keySize); 1133 1134 if (!shader_program) { 1135 shader_program = create_new_program(ctx, &key); 1136 1137 _mesa_shader_cache_insert(ctx, ctx->FragmentProgram.Cache, 1138 &key, keySize, shader_program); 1139 } 1140 1141 return shader_program; 1142} 1143 1144} 1145