• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "util/glheader.h"
31 #include "main/context.h"
32 
33 #include "main/macros.h"
34 #include "main/state.h"
35 #include "main/texenvprogram.h"
36 #include "main/texobj.h"
37 #include "program/program.h"
38 #include "program/prog_cache.h"
39 #include "program/prog_statevars.h"
40 #include "program/prog_to_nir.h"
41 #include "util/bitscan.h"
42 
43 #include "state_tracker/st_context.h"
44 #include "state_tracker/st_program.h"
45 #include "state_tracker/st_nir.h"
46 
47 #include "compiler/nir/nir_builder.h"
48 #include "compiler/nir/nir_builtin_builder.h"
49 
50 /*
51  * Note on texture units:
52  *
53  * The number of texture units supported by fixed-function fragment
54  * processing is MAX_TEXTURE_COORD_UNITS, not MAX_TEXTURE_IMAGE_UNITS.
55  * That's because there's a one-to-one correspondence between texture
56  * coordinates and samplers in fixed-function processing.
57  *
58  * Since fixed-function vertex processing is limited to MAX_TEXTURE_COORD_UNITS
59  * sets of texcoords, so is fixed-function fragment processing.
60  *
61  * We can safely use ctx->Const.MaxTextureUnits for loop bounds.
62  */
63 
64 
65 static GLboolean
texenv_doing_secondary_color(struct gl_context * ctx)66 texenv_doing_secondary_color(struct gl_context *ctx)
67 {
68    if (ctx->Light.Enabled &&
69        (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))
70       return GL_TRUE;
71 
72    if (ctx->Fog.ColorSumEnabled)
73       return GL_TRUE;
74 
75    return GL_FALSE;
76 }
77 
78 struct state_key {
79    GLuint nr_enabled_units:4;
80    GLuint separate_specular:1;
81    GLuint fog_mode:2;          /**< FOG_x */
82    GLuint inputs_available:12;
83    GLuint num_draw_buffers:4;
84 
85    /* NOTE: This array of structs must be last! (see "keySize" below) */
86    struct {
87       GLuint enabled:1;
88       GLuint source_index:4;   /**< TEXTURE_x_INDEX */
89       GLuint shadow:1;
90 
91       /***
92        * These are taken from struct gl_tex_env_combine_packed
93        * @{
94        */
95       GLuint ModeRGB:4;
96       GLuint ModeA:4;
97       GLuint ScaleShiftRGB:2;
98       GLuint ScaleShiftA:2;
99       GLuint NumArgsRGB:3;
100       GLuint NumArgsA:3;
101       struct gl_tex_env_argument ArgsRGB[MAX_COMBINER_TERMS];
102       struct gl_tex_env_argument ArgsA[MAX_COMBINER_TERMS];
103       /** @} */
104    } unit[MAX_TEXTURE_COORD_UNITS];
105 };
106 
107 
108 /**
109  * Do we need to clamp the results of the given texture env/combine mode?
110  * If the inputs to the mode are in [0,1] we don't always have to clamp
111  * the results.
112  */
113 static GLboolean
need_saturate(GLuint mode)114 need_saturate( GLuint mode )
115 {
116    switch (mode) {
117    case TEXENV_MODE_REPLACE:
118    case TEXENV_MODE_MODULATE:
119    case TEXENV_MODE_INTERPOLATE:
120       return GL_FALSE;
121    case TEXENV_MODE_ADD:
122    case TEXENV_MODE_ADD_SIGNED:
123    case TEXENV_MODE_SUBTRACT:
124    case TEXENV_MODE_DOT3_RGB:
125    case TEXENV_MODE_DOT3_RGB_EXT:
126    case TEXENV_MODE_DOT3_RGBA:
127    case TEXENV_MODE_DOT3_RGBA_EXT:
128    case TEXENV_MODE_MODULATE_ADD_ATI:
129    case TEXENV_MODE_MODULATE_SIGNED_ADD_ATI:
130    case TEXENV_MODE_MODULATE_SUBTRACT_ATI:
131    case TEXENV_MODE_ADD_PRODUCTS_NV:
132    case TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV:
133       return GL_TRUE;
134    default:
135       assert(0);
136       return GL_FALSE;
137    }
138 }
139 
140 #define VERT_BIT_TEX_ANY    (0xff << VERT_ATTRIB_TEX0)
141 
142 /**
143  * Identify all possible varying inputs.  The fragment program will
144  * never reference non-varying inputs, but will track them via state
145  * constants instead.
146  *
147  * This function figures out all the inputs that the fragment program
148  * has access to and filters input bitmask.
149  */
filter_fp_input_mask(GLbitfield fp_inputs,struct gl_context * ctx)150 static GLbitfield filter_fp_input_mask( GLbitfield fp_inputs,
151                                         struct gl_context *ctx )
152 {
153    if (ctx->VertexProgram._Overriden) {
154       /* Somebody's messing with the vertex program and we don't have
155        * a clue what's happening.  Assume that it could be producing
156        * all possible outputs.
157        */
158       return fp_inputs;
159    }
160 
161    if (ctx->RenderMode == GL_FEEDBACK) {
162       /* _NEW_RENDERMODE */
163       return fp_inputs & (VARYING_BIT_COL0 | VARYING_BIT_TEX0);
164    }
165 
166    /* _NEW_PROGRAM */
167    const GLboolean vertexShader =
168          ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] != NULL;
169    const GLboolean vertexProgram = _mesa_arb_vertex_program_enabled(ctx);
170 
171    if (!(vertexProgram || vertexShader)) {
172       /* Fixed function vertex logic */
173       GLbitfield possible_inputs = 0;
174 
175       GLbitfield varying_inputs = ctx->VertexProgram._VaryingInputs;
176       /* We only update ctx->VertexProgram._VaryingInputs when in VP_MODE_FF _VPMode */
177       assert(VP_MODE_FF == ctx->VertexProgram._VPMode);
178 
179       /* These get generated in the setup routine regardless of the
180        * vertex program:
181        */
182       /* _NEW_POINT */
183       if (ctx->Point.PointSprite) {
184          /* All texture varyings are possible to use */
185          possible_inputs = VARYING_BITS_TEX_ANY;
186       }
187       else {
188          const GLbitfield possible_tex_inputs =
189                ctx->Texture._TexGenEnabled |
190                ctx->Texture._TexMatEnabled |
191                ((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0);
192 
193          possible_inputs = (possible_tex_inputs << VARYING_SLOT_TEX0);
194       }
195 
196       /* First look at what values may be computed by the generated
197        * vertex program:
198        */
199       if (ctx->Light.Enabled) {
200          possible_inputs |= VARYING_BIT_COL0;
201 
202          if (texenv_doing_secondary_color(ctx))
203             possible_inputs |= VARYING_BIT_COL1;
204       }
205 
206       /* Then look at what might be varying as a result of enabled
207        * arrays, etc:
208        */
209       if (varying_inputs & VERT_BIT_COLOR0)
210          possible_inputs |= VARYING_BIT_COL0;
211       if (varying_inputs & VERT_BIT_COLOR1)
212          possible_inputs |= VARYING_BIT_COL1;
213 
214       return fp_inputs & possible_inputs;
215    }
216 
217    /* calculate from vp->outputs */
218    struct gl_program *vprog;
219 
220    /* Choose GLSL vertex shader over ARB vertex program.  Need this
221     * since vertex shader state validation comes after fragment state
222     * validation (see additional comments in state.c).
223     */
224    if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY] != NULL)
225       vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
226    else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] != NULL)
227       vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
228    else if (vertexShader)
229       vprog = ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
230    else
231       vprog = ctx->VertexProgram.Current;
232 
233    GLbitfield possible_inputs = vprog->info.outputs_written;
234 
235    /* These get generated in the setup routine regardless of the
236     * vertex program:
237     */
238    /* _NEW_POINT */
239    if (ctx->Point.PointSprite) {
240       /* All texture varyings are possible to use */
241       possible_inputs |= VARYING_BITS_TEX_ANY;
242    }
243 
244    return fp_inputs & possible_inputs;
245 }
246 
247 
248 /**
249  * Examine current texture environment state and generate a unique
250  * key to identify it.
251  */
make_state_key(struct gl_context * ctx,struct state_key * key)252 static GLuint make_state_key( struct gl_context *ctx,  struct state_key *key )
253 {
254    GLbitfield inputs_referenced = VARYING_BIT_COL0;
255    GLbitfield mask;
256    GLuint keySize;
257 
258    memset(key, 0, sizeof(*key));
259 
260    /* _NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE */
261    mask = ctx->Texture._EnabledCoordUnits;
262    int i = -1;
263    while (mask) {
264       i = u_bit_scan(&mask);
265       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
266       const struct gl_texture_object *texObj = texUnit->_Current;
267       const struct gl_tex_env_combine_packed *comb =
268          &ctx->Texture.FixedFuncUnit[i]._CurrentCombinePacked;
269 
270       if (!texObj)
271          continue;
272 
273       key->unit[i].enabled = 1;
274       inputs_referenced |= VARYING_BIT_TEX(i);
275 
276       key->unit[i].source_index = texObj->TargetIndex;
277 
278       const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, i);
279       if (samp->Attrib.CompareMode == GL_COMPARE_R_TO_TEXTURE) {
280          const GLenum format = _mesa_texture_base_format(texObj);
281          key->unit[i].shadow = (format == GL_DEPTH_COMPONENT ||
282                                 format == GL_DEPTH_STENCIL_EXT);
283       }
284 
285       key->unit[i].ModeRGB = comb->ModeRGB;
286       key->unit[i].ModeA = comb->ModeA;
287       key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB;
288       key->unit[i].ScaleShiftA = comb->ScaleShiftA;
289       key->unit[i].NumArgsRGB = comb->NumArgsRGB;
290       key->unit[i].NumArgsA = comb->NumArgsA;
291 
292       memcpy(key->unit[i].ArgsRGB, comb->ArgsRGB, sizeof comb->ArgsRGB);
293       memcpy(key->unit[i].ArgsA, comb->ArgsA, sizeof comb->ArgsA);
294    }
295 
296    key->nr_enabled_units = i + 1;
297 
298    /* _NEW_FOG */
299    if (texenv_doing_secondary_color(ctx)) {
300       key->separate_specular = 1;
301       inputs_referenced |= VARYING_BIT_COL1;
302    }
303 
304    /* _NEW_FOG */
305    key->fog_mode = ctx->Fog._PackedEnabledMode;
306 
307    /* _NEW_BUFFERS */
308    key->num_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
309 
310    /* _NEW_COLOR */
311    if (ctx->Color.AlphaEnabled && key->num_draw_buffers == 0) {
312       /* if alpha test is enabled we need to emit at least one color */
313       key->num_draw_buffers = 1;
314    }
315 
316    key->inputs_available = filter_fp_input_mask(inputs_referenced, ctx);
317 
318    /* compute size of state key, ignoring unused texture units */
319    keySize = sizeof(*key) - sizeof(key->unit)
320       + key->nr_enabled_units * sizeof(key->unit[0]);
321 
322    return keySize;
323 }
324 
325 
326 /** State used to build the fragment program:
327  */
328 struct texenv_fragment_program {
329    nir_builder *b;
330    struct gl_program_parameter_list *state_params;
331 
332    struct state_key *state;
333 
334    nir_variable *sampler_vars[MAX_TEXTURE_COORD_UNITS];
335 
336    nir_def *src_texture[MAX_TEXTURE_COORD_UNITS];
337    /* ssa-def containing each texture unit's sampled texture color,
338     * else NULL.
339     */
340 
341    nir_def *src_previous;   /**< Color from previous stage */
342 };
343 
344 static nir_variable *
register_state_var(struct texenv_fragment_program * p,gl_state_index s0,gl_state_index s1,gl_state_index s2,gl_state_index s3,const struct glsl_type * type)345 register_state_var(struct texenv_fragment_program *p,
346                    gl_state_index s0,
347                    gl_state_index s1,
348                    gl_state_index s2,
349                    gl_state_index s3,
350                    const struct glsl_type *type)
351 {
352    gl_state_index16 tokens[STATE_LENGTH];
353    tokens[0] = s0;
354    tokens[1] = s1;
355    tokens[2] = s2;
356    tokens[3] = s3;
357    nir_variable *var = nir_find_state_variable(p->b->shader, tokens);
358    if (var)
359       return var;
360 
361    int loc = _mesa_add_state_reference(p->state_params, tokens);
362 
363    char *name = _mesa_program_state_string(tokens);
364    var = nir_variable_create(p->b->shader, nir_var_uniform, type, name);
365    free(name);
366 
367    var->num_state_slots = 1;
368    var->state_slots = ralloc_array(var, nir_state_slot, 1);
369    var->data.driver_location = loc;
370    memcpy(var->state_slots[0].tokens, tokens,
371           sizeof(var->state_slots[0].tokens));
372 
373    p->b->shader->num_uniforms++;
374    return var;
375 }
376 
377 static nir_def *
load_state_var(struct texenv_fragment_program * p,gl_state_index s0,gl_state_index s1,gl_state_index s2,gl_state_index s3,const struct glsl_type * type)378 load_state_var(struct texenv_fragment_program *p,
379                gl_state_index s0,
380                gl_state_index s1,
381                gl_state_index s2,
382                gl_state_index s3,
383                const struct glsl_type *type)
384 {
385    nir_variable *var = register_state_var(p, s0, s1, s2, s3, type);
386    return nir_load_var(p->b, var);
387 }
388 
389 static nir_def *
load_input(struct texenv_fragment_program * p,gl_varying_slot slot)390 load_input(struct texenv_fragment_program *p, gl_varying_slot slot)
391 {
392    nir_def *baryc = nir_load_barycentric_pixel(p->b, 32);
393 
394    if (slot != VARYING_SLOT_COL0 && slot != VARYING_SLOT_COL1) {
395       nir_intrinsic_set_interp_mode(nir_instr_as_intrinsic(baryc->parent_instr),
396                                     INTERP_MODE_SMOOTH);
397    }
398 
399    return nir_load_interpolated_input(p->b, 4, 32, baryc,
400                                       nir_imm_int(p->b, 0),
401                                       .io_semantics.location = slot);
402 }
403 
404 static nir_def *
get_current_attrib(struct texenv_fragment_program * p,GLuint attrib)405 get_current_attrib(struct texenv_fragment_program *p, GLuint attrib)
406 {
407    return load_state_var(p, STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED,
408                          attrib, 0, 0,
409                          glsl_vec4_type());
410 }
411 
412 static nir_def *
get_gl_Color(struct texenv_fragment_program * p)413 get_gl_Color(struct texenv_fragment_program *p)
414 {
415    if (p->state->inputs_available & VARYING_BIT_COL0) {
416       return load_input(p, VARYING_SLOT_COL0);
417    } else {
418       return get_current_attrib(p, VERT_ATTRIB_COLOR0);
419    }
420 }
421 
422 static nir_def *
get_source(struct texenv_fragment_program * p,GLuint src,GLuint unit)423 get_source(struct texenv_fragment_program *p,
424            GLuint src, GLuint unit)
425 {
426    switch (src) {
427    case TEXENV_SRC_TEXTURE:
428       return p->src_texture[unit];
429 
430    case TEXENV_SRC_TEXTURE0:
431    case TEXENV_SRC_TEXTURE1:
432    case TEXENV_SRC_TEXTURE2:
433    case TEXENV_SRC_TEXTURE3:
434    case TEXENV_SRC_TEXTURE4:
435    case TEXENV_SRC_TEXTURE5:
436    case TEXENV_SRC_TEXTURE6:
437    case TEXENV_SRC_TEXTURE7:
438       return p->src_texture[src - TEXENV_SRC_TEXTURE0];
439 
440    case TEXENV_SRC_CONSTANT:
441       return load_state_var(p, STATE_TEXENV_COLOR,
442                             unit, 0, 0,
443                             glsl_vec4_type());
444 
445    case TEXENV_SRC_PRIMARY_COLOR:
446       return get_gl_Color(p);
447 
448    case TEXENV_SRC_ZERO:
449       return nir_imm_zero(p->b, 4, 32);
450 
451    case TEXENV_SRC_ONE:
452       return nir_imm_vec4(p->b, 1.0f, 1.0f, 1.0f, 1.0f);
453 
454    case TEXENV_SRC_PREVIOUS:
455       if (!p->src_previous) {
456          return get_gl_Color(p);
457       } else {
458          return p->src_previous;
459       }
460 
461    default:
462       assert(0);
463       return NULL;
464    }
465 }
466 
467 static nir_def *
emit_combine_source(struct texenv_fragment_program * p,GLuint unit,GLuint source,GLuint operand)468 emit_combine_source(struct texenv_fragment_program *p,
469                     GLuint unit,
470                     GLuint source,
471                     GLuint operand)
472 {
473    nir_def *src;
474 
475    src = get_source(p, source, unit);
476 
477    switch (operand) {
478    case TEXENV_OPR_ONE_MINUS_COLOR:
479       return nir_fsub_imm(p->b, 1.0, src);
480 
481    case TEXENV_OPR_ALPHA:
482       return src->num_components == 1 ? src : nir_channel(p->b, src, 3);
483 
484    case TEXENV_OPR_ONE_MINUS_ALPHA: {
485       nir_def *scalar =
486          src->num_components == 1 ? src : nir_channel(p->b, src, 3);
487 
488       return nir_fsub_imm(p->b, 1.0, scalar);
489    }
490 
491    case TEXENV_OPR_COLOR:
492       return src;
493 
494    default:
495       assert(0);
496       return src;
497    }
498 }
499 
500 /**
501  * Check if the RGB and Alpha sources and operands match for the given
502  * texture unit's combinder state.  When the RGB and A sources and
503  * operands match, we can emit fewer instructions.
504  */
args_match(const struct state_key * key,GLuint unit)505 static GLboolean args_match( const struct state_key *key, GLuint unit )
506 {
507    GLuint i, numArgs = key->unit[unit].NumArgsRGB;
508 
509    for (i = 0; i < numArgs; i++) {
510       if (key->unit[unit].ArgsA[i].Source != key->unit[unit].ArgsRGB[i].Source)
511          return GL_FALSE;
512 
513       switch (key->unit[unit].ArgsA[i].Operand) {
514       case TEXENV_OPR_ALPHA:
515          switch (key->unit[unit].ArgsRGB[i].Operand) {
516          case TEXENV_OPR_COLOR:
517          case TEXENV_OPR_ALPHA:
518             break;
519          default:
520             return GL_FALSE;
521          }
522          break;
523       case TEXENV_OPR_ONE_MINUS_ALPHA:
524          switch (key->unit[unit].ArgsRGB[i].Operand) {
525          case TEXENV_OPR_ONE_MINUS_COLOR:
526          case TEXENV_OPR_ONE_MINUS_ALPHA:
527             break;
528          default:
529             return GL_FALSE;
530          }
531          break;
532       default:
533          return GL_FALSE;        /* impossible */
534       }
535    }
536 
537    return GL_TRUE;
538 }
539 
540 static nir_def *
smear(nir_builder * b,nir_def * val)541 smear(nir_builder *b, nir_def *val)
542 {
543    if (val->num_components != 1)
544       return val;
545 
546    return nir_replicate(b, val, 4);
547 }
548 
549 static nir_def *
emit_combine(struct texenv_fragment_program * p,GLuint unit,GLuint nr,GLuint mode,const struct gl_tex_env_argument * opt)550 emit_combine(struct texenv_fragment_program *p,
551              GLuint unit,
552              GLuint nr,
553              GLuint mode,
554              const struct gl_tex_env_argument *opt)
555 {
556    nir_def *src[MAX_COMBINER_TERMS];
557    nir_def *tmp0, *tmp1;
558    GLuint i;
559 
560    assert(nr <= MAX_COMBINER_TERMS);
561 
562    for (i = 0; i < nr; i++)
563       src[i] = emit_combine_source( p, unit, opt[i].Source, opt[i].Operand );
564 
565    switch (mode) {
566    case TEXENV_MODE_REPLACE:
567       return src[0];
568 
569    case TEXENV_MODE_MODULATE:
570       return nir_fmul(p->b, src[0], src[1]);
571 
572    case TEXENV_MODE_ADD:
573       return nir_fadd(p->b, src[0], src[1]);
574 
575    case TEXENV_MODE_ADD_SIGNED:
576       return nir_fadd_imm(p->b, nir_fadd(p->b, src[0], src[1]), -0.5f);
577 
578    case TEXENV_MODE_INTERPOLATE:
579       return nir_flrp(p->b, src[1], src[0], src[2]);
580 
581    case TEXENV_MODE_SUBTRACT:
582       return nir_fsub(p->b, src[0], src[1]);
583 
584    case TEXENV_MODE_DOT3_RGBA:
585    case TEXENV_MODE_DOT3_RGBA_EXT:
586    case TEXENV_MODE_DOT3_RGB_EXT:
587    case TEXENV_MODE_DOT3_RGB:
588       tmp0 = nir_fadd_imm(p->b, nir_fmul_imm(p->b, src[0], 2.0f), -1.0f);
589       tmp1 = nir_fadd_imm(p->b, nir_fmul_imm(p->b, src[1], 2.0f), -1.0f);
590       return nir_fdot3(p->b, smear(p->b, tmp0), smear(p->b, tmp1));
591 
592    case TEXENV_MODE_MODULATE_ADD_ATI:
593       return nir_fmad(p->b, src[0], src[2], src[1]);
594 
595    case TEXENV_MODE_MODULATE_SIGNED_ADD_ATI:
596       return nir_fadd_imm(p->b,
597                           nir_fadd(p->b,
598                                    nir_fmul(p->b, src[0], src[2]),
599                                    src[1]),
600                           -0.5f);
601 
602    case TEXENV_MODE_MODULATE_SUBTRACT_ATI:
603       return nir_fsub(p->b, nir_fmul(p->b, src[0], src[2]), src[1]);
604 
605    case TEXENV_MODE_ADD_PRODUCTS_NV:
606       return nir_fadd(p->b, nir_fmul(p->b, src[0], src[1]),
607                             nir_fmul(p->b, src[2], src[3]));
608 
609    case TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV:
610       return nir_fadd_imm(p->b,
611                           nir_fadd(p->b,
612                                    nir_fmul(p->b, src[0], src[1]),
613                                    nir_fmul(p->b, src[2], src[3])),
614                           -0.5f);
615    default:
616       assert(0);
617       return src[0];
618    }
619 }
620 
621 /**
622  * Generate instructions for one texture unit's env/combiner mode.
623  */
624 static nir_def *
emit_texenv(struct texenv_fragment_program * p,GLuint unit)625 emit_texenv(struct texenv_fragment_program *p, GLuint unit)
626 {
627    const struct state_key *key = p->state;
628    GLboolean rgb_saturate, alpha_saturate;
629    GLuint rgb_shift, alpha_shift;
630 
631    if (!key->unit[unit].enabled) {
632       return get_source(p, TEXENV_SRC_PREVIOUS, 0);
633    }
634 
635    switch (key->unit[unit].ModeRGB) {
636    case TEXENV_MODE_DOT3_RGB_EXT:
637       alpha_shift = key->unit[unit].ScaleShiftA;
638       rgb_shift = 0;
639       break;
640    case TEXENV_MODE_DOT3_RGBA_EXT:
641       alpha_shift = 0;
642       rgb_shift = 0;
643       break;
644    default:
645       rgb_shift = key->unit[unit].ScaleShiftRGB;
646       alpha_shift = key->unit[unit].ScaleShiftA;
647       break;
648    }
649 
650    /* If we'll do rgb/alpha shifting don't saturate in emit_combine().
651     * We don't want to clamp twice.
652     */
653    if (rgb_shift)
654       rgb_saturate = GL_FALSE;  /* saturate after rgb shift */
655    else if (need_saturate(key->unit[unit].ModeRGB))
656       rgb_saturate = GL_TRUE;
657    else
658       rgb_saturate = GL_FALSE;
659 
660    if (alpha_shift)
661       alpha_saturate = GL_FALSE;  /* saturate after alpha shift */
662    else if (need_saturate(key->unit[unit].ModeA))
663       alpha_saturate = GL_TRUE;
664    else
665       alpha_saturate = GL_FALSE;
666 
667    nir_def *val;
668 
669    /* Emit the RGB and A combine ops
670     */
671    if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
672        args_match(key, unit)) {
673       val = emit_combine(p, unit,
674                          key->unit[unit].NumArgsRGB,
675                          key->unit[unit].ModeRGB,
676                          key->unit[unit].ArgsRGB);
677       val = smear(p->b, val);
678       if (rgb_saturate)
679          val = nir_fsat(p->b, val);
680    }
681    else if (key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA_EXT ||
682             key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA) {
683       val = emit_combine(p, unit,
684                          key->unit[unit].NumArgsRGB,
685                          key->unit[unit].ModeRGB,
686                          key->unit[unit].ArgsRGB);
687       val = smear(p->b, val);
688       if (rgb_saturate)
689          val = nir_fsat(p->b, val);
690    }
691    else {
692       /* Need to do something to stop from re-emitting identical
693        * argument calculations here:
694        */
695       val = emit_combine(p, unit,
696                          key->unit[unit].NumArgsRGB,
697                          key->unit[unit].ModeRGB,
698                          key->unit[unit].ArgsRGB);
699       val = smear(p->b, val);
700       if (rgb_saturate)
701          val = nir_fsat(p->b, val);
702       nir_def *rgb = val;
703 
704       val = emit_combine(p, unit,
705                          key->unit[unit].NumArgsA,
706                          key->unit[unit].ModeA,
707                          key->unit[unit].ArgsA);
708 
709       if (val->num_components != 1)
710          val = nir_channel(p->b, val, 3);
711 
712       if (alpha_saturate)
713          val = nir_fsat(p->b, val);
714       nir_def *a = val;
715 
716       val = nir_vector_insert_imm(p->b, rgb, a, 3);
717    }
718 
719    /* Deal with the final shift:
720     */
721    if (alpha_shift || rgb_shift) {
722       nir_def *shift;
723 
724       if (rgb_shift == alpha_shift) {
725          shift = nir_imm_float(p->b, (float)(1 << rgb_shift));
726       }
727       else {
728          shift = nir_imm_vec4(p->b,
729             (float)(1 << rgb_shift),
730             (float)(1 << rgb_shift),
731             (float)(1 << rgb_shift),
732             (float)(1 << alpha_shift));
733       }
734 
735       return nir_fsat(p->b, nir_fmul(p->b, val, shift));
736    }
737    else
738       return val;
739 }
740 
741 
742 /**
743  * Generate instruction for getting a texture source term.
744  */
745 static void
load_texture(struct texenv_fragment_program * p,GLuint unit)746 load_texture(struct texenv_fragment_program *p, GLuint unit)
747 {
748    if (p->src_texture[unit])
749       return;
750 
751    const GLuint texTarget = p->state->unit[unit].source_index;
752    nir_def *texcoord;
753 
754    if (!(p->state->inputs_available & (VARYING_BIT_TEX0 << unit))) {
755       texcoord = get_current_attrib(p, VERT_ATTRIB_TEX0 + unit);
756    } else {
757       texcoord = load_input(p, VARYING_SLOT_TEX0 + unit);
758    }
759 
760    if (!p->state->unit[unit].enabled) {
761       p->src_texture[unit] = nir_imm_zero(p->b, 4, 32);
762       return ;
763    }
764 
765    unsigned num_srcs = 4;
766    if (p->state->unit[unit].shadow)
767       num_srcs++;
768 
769    nir_tex_instr *tex = nir_tex_instr_create(p->b->shader, num_srcs);
770    tex->op = nir_texop_tex;
771    tex->dest_type = nir_type_float32;
772    tex->texture_index = unit;
773    tex->sampler_index = unit;
774 
775    tex->sampler_dim =
776       _mesa_texture_index_to_sampler_dim(texTarget,
777                                          &tex->is_array);
778 
779    tex->coord_components =
780       glsl_get_sampler_dim_coordinate_components(tex->sampler_dim);
781    if (tex->is_array)
782       tex->coord_components++;
783 
784    nir_variable *var = p->sampler_vars[unit];
785    if (!var) {
786       const struct glsl_type *sampler_type =
787          glsl_sampler_type(tex->sampler_dim,
788                            p->state->unit[unit].shadow,
789                            tex->is_array, GLSL_TYPE_FLOAT);
790 
791       var = nir_variable_create(p->b->shader, nir_var_uniform,
792                                 sampler_type,
793                                 ralloc_asprintf(p->b->shader,
794                                                 "sampler_%d", unit));
795       var->data.binding = unit;
796       var->data.explicit_binding = true;
797 
798       p->sampler_vars[unit] = var;
799    }
800 
801    nir_deref_instr *deref = nir_build_deref_var(p->b, var);
802    tex->src[0] = nir_tex_src_for_ssa(nir_tex_src_texture_deref,
803                                      &deref->def);
804    tex->src[1] = nir_tex_src_for_ssa(nir_tex_src_sampler_deref,
805                                      &deref->def);
806 
807    nir_def *src2 =
808       nir_channels(p->b, texcoord,
809                    nir_component_mask(tex->coord_components));
810    tex->src[2] = nir_tex_src_for_ssa(nir_tex_src_coord, src2);
811 
812    tex->src[3] = nir_tex_src_for_ssa(nir_tex_src_projector,
813                                      nir_channel(p->b, texcoord, 3));
814 
815    if (p->state->unit[unit].shadow) {
816       tex->is_shadow = true;
817       nir_def *src4 =
818          nir_channel(p->b, texcoord, tex->coord_components);
819       tex->src[4] = nir_tex_src_for_ssa(nir_tex_src_comparator, src4);
820    }
821 
822    nir_def_init(&tex->instr, &tex->def, 4, 32);
823    p->src_texture[unit] = &tex->def;
824 
825    nir_builder_instr_insert(p->b, &tex->instr);
826    BITSET_SET(p->b->shader->info.textures_used, unit);
827    BITSET_SET(p->b->shader->info.samplers_used, unit);
828 }
829 
830 static void
load_texenv_source(struct texenv_fragment_program * p,GLuint src,GLuint unit)831 load_texenv_source(struct texenv_fragment_program *p,
832                    GLuint src, GLuint unit)
833 {
834    switch (src) {
835    case TEXENV_SRC_TEXTURE:
836       load_texture(p, unit);
837       break;
838 
839    case TEXENV_SRC_TEXTURE0:
840    case TEXENV_SRC_TEXTURE1:
841    case TEXENV_SRC_TEXTURE2:
842    case TEXENV_SRC_TEXTURE3:
843    case TEXENV_SRC_TEXTURE4:
844    case TEXENV_SRC_TEXTURE5:
845    case TEXENV_SRC_TEXTURE6:
846    case TEXENV_SRC_TEXTURE7:
847       load_texture(p, src - TEXENV_SRC_TEXTURE0);
848       break;
849 
850    default:
851       /* not a texture src - do nothing */
852       break;
853    }
854 }
855 
856 
857 /**
858  * Generate instructions for loading all texture source terms.
859  */
860 static GLboolean
load_texunit_sources(struct texenv_fragment_program * p,GLuint unit)861 load_texunit_sources(struct texenv_fragment_program *p, GLuint unit)
862 {
863    const struct state_key *key = p->state;
864    GLuint i;
865 
866    for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
867       load_texenv_source( p, key->unit[unit].ArgsRGB[i].Source, unit );
868    }
869 
870    for (i = 0; i < key->unit[unit].NumArgsA; i++) {
871       load_texenv_source( p, key->unit[unit].ArgsA[i].Source, unit );
872    }
873 
874    return GL_TRUE;
875 }
876 
877 static void
emit_instructions(struct texenv_fragment_program * p)878 emit_instructions(struct texenv_fragment_program *p)
879 {
880    struct state_key *key = p->state;
881    GLuint unit;
882 
883    if (key->nr_enabled_units) {
884       /* First pass - to support texture_env_crossbar, first identify
885        * all referenced texture sources and emit texld instructions
886        * for each:
887        */
888       for (unit = 0; unit < key->nr_enabled_units; unit++)
889          if (key->unit[unit].enabled) {
890             load_texunit_sources(p, unit);
891          }
892 
893       /* Second pass - emit combine instructions to build final color:
894        */
895       for (unit = 0; unit < key->nr_enabled_units; unit++) {
896          if (key->unit[unit].enabled) {
897             p->src_previous = emit_texenv(p, unit);
898          }
899       }
900    }
901 
902    nir_def *cf = get_source(p, TEXENV_SRC_PREVIOUS, 0);
903 
904    if (key->separate_specular) {
905       nir_def *spec_result = cf;
906 
907       nir_def *secondary;
908       if (p->state->inputs_available & VARYING_BIT_COL1)
909          secondary = load_input(p, VARYING_SLOT_COL1);
910       else
911          secondary = get_current_attrib(p, VERT_ATTRIB_COLOR1);
912 
913       secondary = nir_vector_insert_imm(p->b, secondary,
914                                         nir_imm_zero(p->b, 1, 32), 3);
915       cf = nir_fadd(p->b, spec_result, secondary);
916    }
917 
918    nir_store_output(p->b, cf, nir_imm_int(p->b, 0),
919                     .io_semantics.location = FRAG_RESULT_COLOR);
920 }
921 
922 /**
923  * Generate a new fragment program which implements the context's
924  * current texture env/combine mode.
925  */
926 static nir_shader *
create_new_program(struct state_key * key,struct gl_program * program,const nir_shader_compiler_options * options)927 create_new_program(struct state_key *key,
928                    struct gl_program *program,
929                    const nir_shader_compiler_options *options)
930 {
931    struct texenv_fragment_program p;
932 
933    memset(&p, 0, sizeof(p));
934    p.state = key;
935 
936    program->Parameters = _mesa_new_parameter_list();
937    p.state_params = _mesa_new_parameter_list();
938 
939    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
940                                                   options,
941                                                   "ff-fs");
942 
943    nir_shader *s = b.shader;
944 
945    s->info.separate_shader = true;
946    s->info.subgroup_size = SUBGROUP_SIZE_UNIFORM;
947    s->info.io_lowered = true;
948 
949    p.b = &b;
950 
951    if (key->num_draw_buffers)
952       emit_instructions(&p);
953 
954    nir_validate_shader(b.shader, "after generating ff-vertex shader");
955 
956    if (key->fog_mode)
957       NIR_PASS(_, b.shader, st_nir_lower_fog, key->fog_mode, p.state_params);
958 
959    _mesa_add_separate_state_parameters(program, p.state_params);
960    _mesa_free_parameter_list(p.state_params);
961 
962    return s;
963 }
964 
965 /**
966  * Return a fragment program which implements the current
967  * fixed-function texture, fog and color-sum operations.
968  */
969 struct gl_program *
_mesa_get_fixed_func_fragment_program(struct gl_context * ctx)970 _mesa_get_fixed_func_fragment_program(struct gl_context *ctx)
971 {
972    struct gl_program *prog;
973    struct state_key key;
974    GLuint keySize;
975 
976    keySize = make_state_key(ctx, &key);
977 
978    prog = (struct gl_program *)
979       _mesa_search_program_cache(ctx->FragmentProgram.Cache,
980                                  &key, keySize);
981 
982    if (!prog) {
983       prog = ctx->Driver.NewProgram(ctx, MESA_SHADER_FRAGMENT, 0, false);
984       if (!prog)
985          return NULL;
986 
987       const struct nir_shader_compiler_options *options =
988          st_get_nir_compiler_options(ctx->st, MESA_SHADER_FRAGMENT);
989 
990       nir_shader *s =
991          create_new_program(&key, prog, options);
992 
993       prog->state.type = PIPE_SHADER_IR_NIR;
994       prog->nir = s;
995 
996       prog->SamplersUsed = s->info.samplers_used[0];
997 
998       /* default mapping from samplers to texture units */
999       for (unsigned i = 0; i < MAX_SAMPLERS; i++)
1000          prog->SamplerUnits[i] = i;
1001 
1002       st_program_string_notify(ctx, GL_FRAGMENT_PROGRAM_ARB, prog);
1003 
1004       _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
1005                                  &key, keySize, prog);
1006    }
1007 
1008    return prog;
1009 }
1010