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