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#include "main/imports.h" 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/ir_to_mesa.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 /* _NEW_VARYING_VP_INPUTS */ 183 GLbitfield varying_inputs = ctx->varying_vp_inputs; 184 185 /* These get generated in the setup routine regardless of the 186 * vertex program: 187 */ 188 /* _NEW_POINT */ 189 if (ctx->Point.PointSprite) { 190 /* All texture varyings are possible to use */ 191 possible_inputs = VARYING_BITS_TEX_ANY; 192 } 193 else { 194 /* _NEW_TEXTURE_STATE */ 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 /* _NEW_LIGHT */ 207 if (ctx->Light.Enabled) { 208 possible_inputs |= VARYING_BIT_COL0; 209 210 if (texenv_doing_secondary_color(ctx)) 211 possible_inputs |= VARYING_BIT_COL1; 212 } 213 214 /* Then look at what might be varying as a result of enabled 215 * arrays, etc: 216 */ 217 if (varying_inputs & VERT_BIT_COLOR0) 218 possible_inputs |= VARYING_BIT_COL0; 219 if (varying_inputs & VERT_BIT_COLOR1) 220 possible_inputs |= VARYING_BIT_COL1; 221 222 return fp_inputs & possible_inputs; 223 } 224 225 /* calculate from vp->outputs */ 226 struct gl_program *vprog; 227 228 /* Choose GLSL vertex shader over ARB vertex program. Need this 229 * since vertex shader state validation comes after fragment state 230 * validation (see additional comments in state.c). 231 */ 232 if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY] != NULL) 233 vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]; 234 else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] != NULL) 235 vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; 236 else if (vertexShader) 237 vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]; 238 else 239 vprog = ctx->VertexProgram.Current; 240 241 GLbitfield possible_inputs = vprog->info.outputs_written; 242 243 /* These get generated in the setup routine regardless of the 244 * vertex program: 245 */ 246 /* _NEW_POINT */ 247 if (ctx->Point.PointSprite) { 248 /* All texture varyings are possible to use */ 249 possible_inputs |= VARYING_BITS_TEX_ANY; 250 } 251 252 return fp_inputs & possible_inputs; 253} 254 255 256/** 257 * Examine current texture environment state and generate a unique 258 * key to identify it. 259 */ 260static GLuint make_state_key( struct gl_context *ctx, struct state_key *key ) 261{ 262 GLbitfield inputs_referenced = VARYING_BIT_COL0; 263 GLbitfield mask; 264 GLuint keySize; 265 266 memset(key, 0, sizeof(*key)); 267 268 /* _NEW_TEXTURE_OBJECT */ 269 mask = ctx->Texture._EnabledCoordUnits; 270 int i = -1; 271 while (mask) { 272 i = u_bit_scan(&mask); 273 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; 274 const struct gl_texture_object *texObj = texUnit->_Current; 275 const struct gl_tex_env_combine_packed *comb = 276 &ctx->Texture.FixedFuncUnit[i]._CurrentCombinePacked; 277 278 if (!texObj) 279 continue; 280 281 key->unit[i].enabled = 1; 282 inputs_referenced |= VARYING_BIT_TEX(i); 283 284 key->unit[i].source_index = texObj->TargetIndex; 285 286 const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, i); 287 if (samp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { 288 const GLenum format = _mesa_texture_base_format(texObj); 289 key->unit[i].shadow = (format == GL_DEPTH_COMPONENT || 290 format == GL_DEPTH_STENCIL_EXT); 291 } 292 293 key->unit[i].ModeRGB = comb->ModeRGB; 294 key->unit[i].ModeA = comb->ModeA; 295 key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB; 296 key->unit[i].ScaleShiftA = comb->ScaleShiftA; 297 key->unit[i].NumArgsRGB = comb->NumArgsRGB; 298 key->unit[i].NumArgsA = comb->NumArgsA; 299 300 memcpy(key->unit[i].ArgsRGB, comb->ArgsRGB, sizeof comb->ArgsRGB); 301 memcpy(key->unit[i].ArgsA, comb->ArgsA, sizeof comb->ArgsA); 302 } 303 304 key->nr_enabled_units = i + 1; 305 306 /* _NEW_LIGHT | _NEW_FOG */ 307 if (texenv_doing_secondary_color(ctx)) { 308 key->separate_specular = 1; 309 inputs_referenced |= VARYING_BIT_COL1; 310 } 311 312 /* _NEW_FOG */ 313 key->fog_mode = ctx->Fog._PackedEnabledMode; 314 315 /* _NEW_BUFFERS */ 316 key->num_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers; 317 318 /* _NEW_COLOR */ 319 if (ctx->Color.AlphaEnabled && key->num_draw_buffers == 0) { 320 /* if alpha test is enabled we need to emit at least one color */ 321 key->num_draw_buffers = 1; 322 } 323 324 key->inputs_available = filter_fp_input_mask(inputs_referenced, ctx); 325 326 /* compute size of state key, ignoring unused texture units */ 327 keySize = sizeof(*key) - sizeof(key->unit) 328 + key->nr_enabled_units * sizeof(key->unit[0]); 329 330 return keySize; 331} 332 333 334/** State used to build the fragment program: 335 */ 336class texenv_fragment_program : public ir_factory { 337public: 338 struct gl_shader_program *shader_program; 339 struct gl_shader *shader; 340 exec_list *top_instructions; 341 struct state_key *state; 342 343 ir_variable *src_texture[MAX_TEXTURE_COORD_UNITS]; 344 /* Reg containing each texture unit's sampled texture color, 345 * else undef. 346 */ 347 348 /* Texcoord override from bumpmapping. */ 349 ir_variable *texcoord_tex[MAX_TEXTURE_COORD_UNITS]; 350 351 /* Reg containing texcoord for a texture unit, 352 * needed for bump mapping, else undef. 353 */ 354 355 ir_rvalue *src_previous; /**< Reg containing color from previous 356 * stage. May need to be decl'd. 357 */ 358}; 359 360static ir_rvalue * 361get_current_attrib(texenv_fragment_program *p, GLuint attrib) 362{ 363 ir_variable *current; 364 ir_rvalue *val; 365 366 current = p->shader->symbols->get_variable("gl_CurrentAttribFragMESA"); 367 assert(current); 368 current->data.max_array_access = MAX2(current->data.max_array_access, (int)attrib); 369 val = new(p->mem_ctx) ir_dereference_variable(current); 370 ir_rvalue *index = new(p->mem_ctx) ir_constant(attrib); 371 return new(p->mem_ctx) ir_dereference_array(val, index); 372} 373 374static ir_rvalue * 375get_gl_Color(texenv_fragment_program *p) 376{ 377 if (p->state->inputs_available & VARYING_BIT_COL0) { 378 ir_variable *var = p->shader->symbols->get_variable("gl_Color"); 379 assert(var); 380 return new(p->mem_ctx) ir_dereference_variable(var); 381 } else { 382 return get_current_attrib(p, VERT_ATTRIB_COLOR0); 383 } 384} 385 386static ir_rvalue * 387get_source(texenv_fragment_program *p, 388 GLuint src, GLuint unit) 389{ 390 ir_variable *var; 391 ir_dereference *deref; 392 393 switch (src) { 394 case TEXENV_SRC_TEXTURE: 395 return new(p->mem_ctx) ir_dereference_variable(p->src_texture[unit]); 396 397 case TEXENV_SRC_TEXTURE0: 398 case TEXENV_SRC_TEXTURE1: 399 case TEXENV_SRC_TEXTURE2: 400 case TEXENV_SRC_TEXTURE3: 401 case TEXENV_SRC_TEXTURE4: 402 case TEXENV_SRC_TEXTURE5: 403 case TEXENV_SRC_TEXTURE6: 404 case TEXENV_SRC_TEXTURE7: 405 return new(p->mem_ctx) 406 ir_dereference_variable(p->src_texture[src - TEXENV_SRC_TEXTURE0]); 407 408 case TEXENV_SRC_CONSTANT: 409 var = p->shader->symbols->get_variable("gl_TextureEnvColor"); 410 assert(var); 411 deref = new(p->mem_ctx) ir_dereference_variable(var); 412 var->data.max_array_access = MAX2(var->data.max_array_access, (int)unit); 413 return new(p->mem_ctx) ir_dereference_array(deref, 414 new(p->mem_ctx) ir_constant(unit)); 415 416 case TEXENV_SRC_PRIMARY_COLOR: 417 var = p->shader->symbols->get_variable("gl_Color"); 418 assert(var); 419 return new(p->mem_ctx) ir_dereference_variable(var); 420 421 case TEXENV_SRC_ZERO: 422 return new(p->mem_ctx) ir_constant(0.0f); 423 424 case TEXENV_SRC_ONE: 425 return new(p->mem_ctx) ir_constant(1.0f); 426 427 case TEXENV_SRC_PREVIOUS: 428 if (!p->src_previous) { 429 return get_gl_Color(p); 430 } else { 431 return p->src_previous->clone(p->mem_ctx, NULL); 432 } 433 434 default: 435 assert(0); 436 return NULL; 437 } 438} 439 440static ir_rvalue * 441emit_combine_source(texenv_fragment_program *p, 442 GLuint unit, 443 GLuint source, 444 GLuint operand) 445{ 446 ir_rvalue *src; 447 448 src = get_source(p, source, unit); 449 450 switch (operand) { 451 case TEXENV_OPR_ONE_MINUS_COLOR: 452 return sub(new(p->mem_ctx) ir_constant(1.0f), src); 453 454 case TEXENV_OPR_ALPHA: 455 return src->type->is_scalar() ? src : swizzle_w(src); 456 457 case TEXENV_OPR_ONE_MINUS_ALPHA: { 458 ir_rvalue *const scalar = src->type->is_scalar() ? src : swizzle_w(src); 459 460 return sub(new(p->mem_ctx) ir_constant(1.0f), scalar); 461 } 462 463 case TEXENV_OPR_COLOR: 464 return src; 465 466 default: 467 assert(0); 468 return src; 469 } 470} 471 472/** 473 * Check if the RGB and Alpha sources and operands match for the given 474 * texture unit's combinder state. When the RGB and A sources and 475 * operands match, we can emit fewer instructions. 476 */ 477static GLboolean args_match( const struct state_key *key, GLuint unit ) 478{ 479 GLuint i, numArgs = key->unit[unit].NumArgsRGB; 480 481 for (i = 0; i < numArgs; i++) { 482 if (key->unit[unit].ArgsA[i].Source != key->unit[unit].ArgsRGB[i].Source) 483 return GL_FALSE; 484 485 switch (key->unit[unit].ArgsA[i].Operand) { 486 case TEXENV_OPR_ALPHA: 487 switch (key->unit[unit].ArgsRGB[i].Operand) { 488 case TEXENV_OPR_COLOR: 489 case TEXENV_OPR_ALPHA: 490 break; 491 default: 492 return GL_FALSE; 493 } 494 break; 495 case TEXENV_OPR_ONE_MINUS_ALPHA: 496 switch (key->unit[unit].ArgsRGB[i].Operand) { 497 case TEXENV_OPR_ONE_MINUS_COLOR: 498 case TEXENV_OPR_ONE_MINUS_ALPHA: 499 break; 500 default: 501 return GL_FALSE; 502 } 503 break; 504 default: 505 return GL_FALSE; /* impossible */ 506 } 507 } 508 509 return GL_TRUE; 510} 511 512static ir_rvalue * 513smear(ir_rvalue *val) 514{ 515 if (!val->type->is_scalar()) 516 return val; 517 518 return swizzle_xxxx(val); 519} 520 521static ir_rvalue * 522emit_combine(texenv_fragment_program *p, 523 GLuint unit, 524 GLuint nr, 525 GLuint mode, 526 const struct gl_tex_env_argument *opt) 527{ 528 ir_rvalue *src[MAX_COMBINER_TERMS]; 529 ir_rvalue *tmp0, *tmp1; 530 GLuint i; 531 532 assert(nr <= MAX_COMBINER_TERMS); 533 534 for (i = 0; i < nr; i++) 535 src[i] = emit_combine_source( p, unit, opt[i].Source, opt[i].Operand ); 536 537 switch (mode) { 538 case TEXENV_MODE_REPLACE: 539 return src[0]; 540 541 case TEXENV_MODE_MODULATE: 542 return mul(src[0], src[1]); 543 544 case TEXENV_MODE_ADD: 545 return add(src[0], src[1]); 546 547 case TEXENV_MODE_ADD_SIGNED: 548 return add(add(src[0], src[1]), new(p->mem_ctx) ir_constant(-0.5f)); 549 550 case TEXENV_MODE_INTERPOLATE: 551 /* Arg0 * (Arg2) + Arg1 * (1-Arg2) */ 552 tmp0 = mul(src[0], src[2]); 553 tmp1 = mul(src[1], sub(new(p->mem_ctx) ir_constant(1.0f), 554 src[2]->clone(p->mem_ctx, NULL))); 555 return add(tmp0, tmp1); 556 557 case TEXENV_MODE_SUBTRACT: 558 return sub(src[0], src[1]); 559 560 case TEXENV_MODE_DOT3_RGBA: 561 case TEXENV_MODE_DOT3_RGBA_EXT: 562 case TEXENV_MODE_DOT3_RGB_EXT: 563 case TEXENV_MODE_DOT3_RGB: { 564 tmp0 = mul(src[0], new(p->mem_ctx) ir_constant(2.0f)); 565 tmp0 = add(tmp0, new(p->mem_ctx) ir_constant(-1.0f)); 566 567 tmp1 = mul(src[1], new(p->mem_ctx) ir_constant(2.0f)); 568 tmp1 = add(tmp1, new(p->mem_ctx) ir_constant(-1.0f)); 569 570 return dot(swizzle_xyz(smear(tmp0)), swizzle_xyz(smear(tmp1))); 571 } 572 case TEXENV_MODE_MODULATE_ADD_ATI: 573 return add(mul(src[0], src[2]), src[1]); 574 575 case TEXENV_MODE_MODULATE_SIGNED_ADD_ATI: 576 return add(add(mul(src[0], src[2]), src[1]), 577 new(p->mem_ctx) ir_constant(-0.5f)); 578 579 case TEXENV_MODE_MODULATE_SUBTRACT_ATI: 580 return sub(mul(src[0], src[2]), src[1]); 581 582 case TEXENV_MODE_ADD_PRODUCTS_NV: 583 return add(mul(src[0], src[1]), mul(src[2], src[3])); 584 585 case TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV: 586 return add(add(mul(src[0], src[1]), mul(src[2], src[3])), 587 new(p->mem_ctx) ir_constant(-0.5f)); 588 default: 589 assert(0); 590 return src[0]; 591 } 592} 593 594/** 595 * Generate instructions for one texture unit's env/combiner mode. 596 */ 597static ir_rvalue * 598emit_texenv(texenv_fragment_program *p, GLuint unit) 599{ 600 const struct state_key *key = p->state; 601 GLboolean rgb_saturate, alpha_saturate; 602 GLuint rgb_shift, alpha_shift; 603 604 if (!key->unit[unit].enabled) { 605 return get_source(p, TEXENV_SRC_PREVIOUS, 0); 606 } 607 608 switch (key->unit[unit].ModeRGB) { 609 case TEXENV_MODE_DOT3_RGB_EXT: 610 alpha_shift = key->unit[unit].ScaleShiftA; 611 rgb_shift = 0; 612 break; 613 case TEXENV_MODE_DOT3_RGBA_EXT: 614 alpha_shift = 0; 615 rgb_shift = 0; 616 break; 617 default: 618 rgb_shift = key->unit[unit].ScaleShiftRGB; 619 alpha_shift = key->unit[unit].ScaleShiftA; 620 break; 621 } 622 623 /* If we'll do rgb/alpha shifting don't saturate in emit_combine(). 624 * We don't want to clamp twice. 625 */ 626 if (rgb_shift) 627 rgb_saturate = GL_FALSE; /* saturate after rgb shift */ 628 else if (need_saturate(key->unit[unit].ModeRGB)) 629 rgb_saturate = GL_TRUE; 630 else 631 rgb_saturate = GL_FALSE; 632 633 if (alpha_shift) 634 alpha_saturate = GL_FALSE; /* saturate after alpha shift */ 635 else if (need_saturate(key->unit[unit].ModeA)) 636 alpha_saturate = GL_TRUE; 637 else 638 alpha_saturate = GL_FALSE; 639 640 ir_variable *temp_var = p->make_temp(glsl_type::vec4_type, "texenv_combine"); 641 ir_dereference *deref; 642 ir_rvalue *val; 643 644 /* Emit the RGB and A combine ops 645 */ 646 if (key->unit[unit].ModeRGB == key->unit[unit].ModeA && 647 args_match(key, unit)) { 648 val = emit_combine(p, unit, 649 key->unit[unit].NumArgsRGB, 650 key->unit[unit].ModeRGB, 651 key->unit[unit].ArgsRGB); 652 val = smear(val); 653 if (rgb_saturate) 654 val = saturate(val); 655 656 p->emit(assign(temp_var, val)); 657 } 658 else if (key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA_EXT || 659 key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA) { 660 ir_rvalue *val = emit_combine(p, unit, 661 key->unit[unit].NumArgsRGB, 662 key->unit[unit].ModeRGB, 663 key->unit[unit].ArgsRGB); 664 val = smear(val); 665 if (rgb_saturate) 666 val = saturate(val); 667 p->emit(assign(temp_var, val)); 668 } 669 else { 670 /* Need to do something to stop from re-emitting identical 671 * argument calculations here: 672 */ 673 val = emit_combine(p, unit, 674 key->unit[unit].NumArgsRGB, 675 key->unit[unit].ModeRGB, 676 key->unit[unit].ArgsRGB); 677 val = swizzle_xyz(smear(val)); 678 if (rgb_saturate) 679 val = saturate(val); 680 p->emit(assign(temp_var, val, WRITEMASK_XYZ)); 681 682 val = emit_combine(p, unit, 683 key->unit[unit].NumArgsA, 684 key->unit[unit].ModeA, 685 key->unit[unit].ArgsA); 686 val = swizzle_w(smear(val)); 687 if (alpha_saturate) 688 val = saturate(val); 689 p->emit(assign(temp_var, val, WRITEMASK_W)); 690 } 691 692 deref = new(p->mem_ctx) ir_dereference_variable(temp_var); 693 694 /* Deal with the final shift: 695 */ 696 if (alpha_shift || rgb_shift) { 697 ir_constant *shift; 698 699 if (rgb_shift == alpha_shift) { 700 shift = new(p->mem_ctx) ir_constant((float)(1 << rgb_shift)); 701 } 702 else { 703 ir_constant_data const_data; 704 705 const_data.f[0] = float(1 << rgb_shift); 706 const_data.f[1] = float(1 << rgb_shift); 707 const_data.f[2] = float(1 << rgb_shift); 708 const_data.f[3] = float(1 << alpha_shift); 709 710 shift = new(p->mem_ctx) ir_constant(glsl_type::vec4_type, 711 &const_data); 712 } 713 714 return saturate(mul(deref, shift)); 715 } 716 else 717 return deref; 718} 719 720 721/** 722 * Generate instruction for getting a texture source term. 723 */ 724static void load_texture( texenv_fragment_program *p, GLuint unit ) 725{ 726 ir_dereference *deref; 727 728 if (p->src_texture[unit]) 729 return; 730 731 const GLuint texTarget = p->state->unit[unit].source_index; 732 ir_rvalue *texcoord; 733 734 if (!(p->state->inputs_available & (VARYING_BIT_TEX0 << unit))) { 735 texcoord = get_current_attrib(p, VERT_ATTRIB_TEX0 + unit); 736 } else if (p->texcoord_tex[unit]) { 737 texcoord = new(p->mem_ctx) ir_dereference_variable(p->texcoord_tex[unit]); 738 } else { 739 ir_variable *tc_array = p->shader->symbols->get_variable("gl_TexCoord"); 740 assert(tc_array); 741 texcoord = new(p->mem_ctx) ir_dereference_variable(tc_array); 742 ir_rvalue *index = new(p->mem_ctx) ir_constant(unit); 743 texcoord = new(p->mem_ctx) ir_dereference_array(texcoord, index); 744 tc_array->data.max_array_access = MAX2(tc_array->data.max_array_access, (int)unit); 745 } 746 747 if (!p->state->unit[unit].enabled) { 748 p->src_texture[unit] = p->make_temp(glsl_type::vec4_type, 749 "dummy_tex"); 750 p->emit(p->src_texture[unit]); 751 752 p->emit(assign(p->src_texture[unit], new(p->mem_ctx) ir_constant(0.0f))); 753 return ; 754 } 755 756 const glsl_type *sampler_type = NULL; 757 int coords = 0; 758 759 switch (texTarget) { 760 case TEXTURE_1D_INDEX: 761 if (p->state->unit[unit].shadow) 762 sampler_type = glsl_type::sampler1DShadow_type; 763 else 764 sampler_type = glsl_type::sampler1D_type; 765 coords = 1; 766 break; 767 case TEXTURE_1D_ARRAY_INDEX: 768 if (p->state->unit[unit].shadow) 769 sampler_type = glsl_type::sampler1DArrayShadow_type; 770 else 771 sampler_type = glsl_type::sampler1DArray_type; 772 coords = 2; 773 break; 774 case TEXTURE_2D_INDEX: 775 if (p->state->unit[unit].shadow) 776 sampler_type = glsl_type::sampler2DShadow_type; 777 else 778 sampler_type = glsl_type::sampler2D_type; 779 coords = 2; 780 break; 781 case TEXTURE_2D_ARRAY_INDEX: 782 if (p->state->unit[unit].shadow) 783 sampler_type = glsl_type::sampler2DArrayShadow_type; 784 else 785 sampler_type = glsl_type::sampler2DArray_type; 786 coords = 3; 787 break; 788 case TEXTURE_RECT_INDEX: 789 if (p->state->unit[unit].shadow) 790 sampler_type = glsl_type::sampler2DRectShadow_type; 791 else 792 sampler_type = glsl_type::sampler2DRect_type; 793 coords = 2; 794 break; 795 case TEXTURE_3D_INDEX: 796 assert(!p->state->unit[unit].shadow); 797 sampler_type = glsl_type::sampler3D_type; 798 coords = 3; 799 break; 800 case TEXTURE_CUBE_INDEX: 801 if (p->state->unit[unit].shadow) 802 sampler_type = glsl_type::samplerCubeShadow_type; 803 else 804 sampler_type = glsl_type::samplerCube_type; 805 coords = 3; 806 break; 807 case TEXTURE_EXTERNAL_INDEX: 808 assert(!p->state->unit[unit].shadow); 809 sampler_type = glsl_type::samplerExternalOES_type; 810 coords = 2; 811 break; 812 } 813 814 p->src_texture[unit] = p->make_temp(glsl_type::vec4_type, 815 "tex"); 816 817 ir_texture *tex = new(p->mem_ctx) ir_texture(ir_tex); 818 819 820 char *sampler_name = ralloc_asprintf(p->mem_ctx, "sampler_%d", unit); 821 ir_variable *sampler = new(p->mem_ctx) ir_variable(sampler_type, 822 sampler_name, 823 ir_var_uniform); 824 p->top_instructions->push_head(sampler); 825 826 /* Set the texture unit for this sampler in the same way that 827 * layout(binding=X) would. 828 */ 829 sampler->data.explicit_binding = true; 830 sampler->data.binding = unit; 831 832 deref = new(p->mem_ctx) ir_dereference_variable(sampler); 833 tex->set_sampler(deref, glsl_type::vec4_type); 834 835 tex->coordinate = new(p->mem_ctx) ir_swizzle(texcoord, 0, 1, 2, 3, coords); 836 837 if (p->state->unit[unit].shadow) { 838 texcoord = texcoord->clone(p->mem_ctx, NULL); 839 tex->shadow_comparator = new(p->mem_ctx) ir_swizzle(texcoord, 840 coords, 0, 0, 0, 841 1); 842 coords++; 843 } 844 845 texcoord = texcoord->clone(p->mem_ctx, NULL); 846 tex->projector = swizzle_w(texcoord); 847 848 p->emit(assign(p->src_texture[unit], tex)); 849} 850 851static void 852load_texenv_source(texenv_fragment_program *p, 853 GLuint src, GLuint unit) 854{ 855 switch (src) { 856 case TEXENV_SRC_TEXTURE: 857 load_texture(p, unit); 858 break; 859 860 case TEXENV_SRC_TEXTURE0: 861 case TEXENV_SRC_TEXTURE1: 862 case TEXENV_SRC_TEXTURE2: 863 case TEXENV_SRC_TEXTURE3: 864 case TEXENV_SRC_TEXTURE4: 865 case TEXENV_SRC_TEXTURE5: 866 case TEXENV_SRC_TEXTURE6: 867 case TEXENV_SRC_TEXTURE7: 868 load_texture(p, src - TEXENV_SRC_TEXTURE0); 869 break; 870 871 default: 872 /* not a texture src - do nothing */ 873 break; 874 } 875} 876 877 878/** 879 * Generate instructions for loading all texture source terms. 880 */ 881static GLboolean 882load_texunit_sources( texenv_fragment_program *p, GLuint unit ) 883{ 884 const struct state_key *key = p->state; 885 GLuint i; 886 887 for (i = 0; i < key->unit[unit].NumArgsRGB; i++) { 888 load_texenv_source( p, key->unit[unit].ArgsRGB[i].Source, unit ); 889 } 890 891 for (i = 0; i < key->unit[unit].NumArgsA; i++) { 892 load_texenv_source( p, key->unit[unit].ArgsA[i].Source, unit ); 893 } 894 895 return GL_TRUE; 896} 897 898/** 899 * Applies the fog calculations. 900 * 901 * This is basically like the ARB_fragment_prorgam fog options. Note 902 * that ffvertex_prog.c produces fogcoord for us when 903 * GL_FOG_COORDINATE_EXT is set to GL_FRAGMENT_DEPTH_EXT. 904 */ 905static ir_rvalue * 906emit_fog_instructions(texenv_fragment_program *p, 907 ir_rvalue *fragcolor) 908{ 909 struct state_key *key = p->state; 910 ir_rvalue *f, *temp; 911 ir_variable *params, *oparams; 912 ir_variable *fogcoord; 913 914 /* Temporary storage for the whole fog result. Fog calculations 915 * only affect rgb so we're hanging on to the .a value of fragcolor 916 * this way. 917 */ 918 ir_variable *fog_result = p->make_temp(glsl_type::vec4_type, "fog_result"); 919 p->emit(assign(fog_result, fragcolor)); 920 921 fragcolor = swizzle_xyz(fog_result); 922 923 oparams = p->shader->symbols->get_variable("gl_FogParamsOptimizedMESA"); 924 assert(oparams); 925 fogcoord = p->shader->symbols->get_variable("gl_FogFragCoord"); 926 assert(fogcoord); 927 params = p->shader->symbols->get_variable("gl_Fog"); 928 assert(params); 929 f = new(p->mem_ctx) ir_dereference_variable(fogcoord); 930 931 ir_variable *f_var = p->make_temp(glsl_type::float_type, "fog_factor"); 932 933 switch (key->fog_mode) { 934 case FOG_LINEAR: 935 /* f = (end - z) / (end - start) 936 * 937 * gl_MesaFogParamsOptimized gives us (-1 / (end - start)) and 938 * (end / (end - start)) so we can generate a single MAD. 939 */ 940 f = add(mul(f, swizzle_x(oparams)), swizzle_y(oparams)); 941 break; 942 case FOG_EXP: 943 /* f = e^(-(density * fogcoord)) 944 * 945 * gl_MesaFogParamsOptimized gives us density/ln(2) so we can 946 * use EXP2 which is generally the native instruction without 947 * having to do any further math on the fog density uniform. 948 */ 949 f = mul(f, swizzle_z(oparams)); 950 f = new(p->mem_ctx) ir_expression(ir_unop_neg, f); 951 f = new(p->mem_ctx) ir_expression(ir_unop_exp2, f); 952 break; 953 case FOG_EXP2: 954 /* f = e^(-(density * fogcoord)^2) 955 * 956 * gl_MesaFogParamsOptimized gives us density/sqrt(ln(2)) so we 957 * can do this like FOG_EXP but with a squaring after the 958 * multiply by density. 959 */ 960 ir_variable *temp_var = p->make_temp(glsl_type::float_type, "fog_temp"); 961 p->emit(assign(temp_var, mul(f, swizzle_w(oparams)))); 962 963 f = mul(temp_var, temp_var); 964 f = new(p->mem_ctx) ir_expression(ir_unop_neg, f); 965 f = new(p->mem_ctx) ir_expression(ir_unop_exp2, f); 966 break; 967 } 968 969 p->emit(assign(f_var, saturate(f))); 970 971 f = sub(new(p->mem_ctx) ir_constant(1.0f), f_var); 972 temp = new(p->mem_ctx) ir_dereference_variable(params); 973 temp = new(p->mem_ctx) ir_dereference_record(temp, "color"); 974 temp = mul(swizzle_xyz(temp), f); 975 976 p->emit(assign(fog_result, add(temp, mul(fragcolor, f_var)), WRITEMASK_XYZ)); 977 978 return new(p->mem_ctx) ir_dereference_variable(fog_result); 979} 980 981static void 982emit_instructions(texenv_fragment_program *p) 983{ 984 struct state_key *key = p->state; 985 GLuint unit; 986 987 if (key->nr_enabled_units) { 988 /* First pass - to support texture_env_crossbar, first identify 989 * all referenced texture sources and emit texld instructions 990 * for each: 991 */ 992 for (unit = 0; unit < key->nr_enabled_units; unit++) 993 if (key->unit[unit].enabled) { 994 load_texunit_sources(p, unit); 995 } 996 997 /* Second pass - emit combine instructions to build final color: 998 */ 999 for (unit = 0; unit < key->nr_enabled_units; unit++) { 1000 if (key->unit[unit].enabled) { 1001 p->src_previous = emit_texenv(p, unit); 1002 } 1003 } 1004 } 1005 1006 ir_rvalue *cf = get_source(p, TEXENV_SRC_PREVIOUS, 0); 1007 1008 if (key->separate_specular) { 1009 ir_variable *spec_result = p->make_temp(glsl_type::vec4_type, 1010 "specular_add"); 1011 p->emit(assign(spec_result, cf)); 1012 1013 ir_rvalue *secondary; 1014 if (p->state->inputs_available & VARYING_BIT_COL1) { 1015 ir_variable *var = 1016 p->shader->symbols->get_variable("gl_SecondaryColor"); 1017 assert(var); 1018 secondary = swizzle_xyz(var); 1019 } else { 1020 secondary = swizzle_xyz(get_current_attrib(p, VERT_ATTRIB_COLOR1)); 1021 } 1022 1023 p->emit(assign(spec_result, add(swizzle_xyz(spec_result), secondary), 1024 WRITEMASK_XYZ)); 1025 1026 cf = new(p->mem_ctx) ir_dereference_variable(spec_result); 1027 } 1028 1029 if (key->fog_mode) { 1030 cf = emit_fog_instructions(p, cf); 1031 } 1032 1033 ir_variable *frag_color = p->shader->symbols->get_variable("gl_FragColor"); 1034 assert(frag_color); 1035 p->emit(assign(frag_color, cf)); 1036} 1037 1038/** 1039 * Generate a new fragment program which implements the context's 1040 * current texture env/combine mode. 1041 */ 1042static struct gl_shader_program * 1043create_new_program(struct gl_context *ctx, struct state_key *key) 1044{ 1045 texenv_fragment_program p; 1046 unsigned int unit; 1047 _mesa_glsl_parse_state *state; 1048 1049 p.mem_ctx = ralloc_context(NULL); 1050 p.shader = _mesa_new_shader(0, MESA_SHADER_FRAGMENT); 1051#ifdef DEBUG 1052 p.shader->SourceChecksum = 0xf18ed; /* fixed */ 1053#endif 1054 p.shader->ir = new(p.shader) exec_list; 1055 state = new(p.shader) _mesa_glsl_parse_state(ctx, MESA_SHADER_FRAGMENT, 1056 p.shader); 1057 p.shader->symbols = state->symbols; 1058 p.top_instructions = p.shader->ir; 1059 p.instructions = p.shader->ir; 1060 p.state = key; 1061 p.shader_program = _mesa_new_shader_program(0); 1062 1063 /* Tell the linker to ignore the fact that we're building a 1064 * separate shader, in case we're in a GLES2 context that would 1065 * normally reject that. The real problem is that we're building a 1066 * fixed function program in a GLES2 context at all, but that's a 1067 * big mess to clean up. 1068 */ 1069 p.shader_program->SeparateShader = GL_TRUE; 1070 1071 /* The legacy GLSL shadow functions follow the depth texture 1072 * mode and return vec4. The GLSL 1.30 shadow functions return float and 1073 * ignore the depth texture mode. That's a shader and state dependency 1074 * that's difficult to deal with. st/mesa uses a simple but not 1075 * completely correct solution: if the shader declares GLSL >= 1.30 and 1076 * the depth texture mode is GL_ALPHA (000X), it sets the XXXX swizzle 1077 * instead. Thus, the GLSL 1.30 shadow function will get the result in .x 1078 * and legacy shadow functions will get it in .w as expected. 1079 * For the fixed-function fragment shader, use 120 to get correct behavior 1080 * for GL_ALPHA. 1081 */ 1082 state->language_version = 120; 1083 1084 state->es_shader = false; 1085 if (_mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external) 1086 state->OES_EGL_image_external_enable = true; 1087 _mesa_glsl_initialize_types(state); 1088 _mesa_glsl_initialize_variables(p.instructions, state); 1089 1090 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 1091 p.src_texture[unit] = NULL; 1092 p.texcoord_tex[unit] = NULL; 1093 } 1094 1095 p.src_previous = NULL; 1096 1097 ir_function *main_f = new(p.mem_ctx) ir_function("main"); 1098 p.emit(main_f); 1099 state->symbols->add_function(main_f); 1100 1101 ir_function_signature *main_sig = 1102 new(p.mem_ctx) ir_function_signature(glsl_type::void_type); 1103 main_sig->is_defined = true; 1104 main_f->add_signature(main_sig); 1105 1106 p.instructions = &main_sig->body; 1107 if (key->num_draw_buffers) 1108 emit_instructions(&p); 1109 1110 validate_ir_tree(p.shader->ir); 1111 1112 const struct gl_shader_compiler_options *options = 1113 &ctx->Const.ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; 1114 1115 /* Conservative approach: Don't optimize here, the linker does it too. */ 1116 if (!ctx->Const.GLSLOptimizeConservatively) { 1117 while (do_common_optimization(p.shader->ir, false, false, options, 1118 ctx->Const.NativeIntegers)) 1119 ; 1120 } 1121 1122 reparent_ir(p.shader->ir, p.shader->ir); 1123 1124 p.shader->CompileStatus = COMPILE_SUCCESS; 1125 p.shader->Version = state->language_version; 1126 p.shader_program->Shaders = 1127 (gl_shader **)malloc(sizeof(*p.shader_program->Shaders)); 1128 p.shader_program->Shaders[0] = p.shader; 1129 p.shader_program->NumShaders = 1; 1130 1131 _mesa_glsl_link_shader(ctx, p.shader_program); 1132 1133 if (!p.shader_program->data->LinkStatus) 1134 _mesa_problem(ctx, "Failed to link fixed function fragment shader: %s\n", 1135 p.shader_program->data->InfoLog); 1136 1137 ralloc_free(p.mem_ctx); 1138 return p.shader_program; 1139} 1140 1141extern "C" { 1142 1143/** 1144 * Return a fragment program which implements the current 1145 * fixed-function texture, fog and color-sum operations. 1146 */ 1147struct gl_shader_program * 1148_mesa_get_fixed_func_fragment_program(struct gl_context *ctx) 1149{ 1150 struct gl_shader_program *shader_program; 1151 struct state_key key; 1152 GLuint keySize; 1153 1154 keySize = make_state_key(ctx, &key); 1155 1156 shader_program = (struct gl_shader_program *) 1157 _mesa_search_program_cache(ctx->FragmentProgram.Cache, 1158 &key, keySize); 1159 1160 if (!shader_program) { 1161 shader_program = create_new_program(ctx, &key); 1162 1163 _mesa_shader_cache_insert(ctx, ctx->FragmentProgram.Cache, 1164 &key, keySize, shader_program); 1165 } 1166 1167 return shader_program; 1168} 1169 1170} 1171