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,const struct glsl_type * type)390 load_input(struct texenv_fragment_program *p, gl_varying_slot slot,
391 const struct glsl_type *type)
392 {
393 nir_variable *var =
394 nir_get_variable_with_location(p->b->shader,
395 nir_var_shader_in,
396 slot,
397 type);
398 var->data.interpolation = INTERP_MODE_NONE;
399 return nir_load_var(p->b, var);
400 }
401
402 static nir_def *
get_current_attrib(struct texenv_fragment_program * p,GLuint attrib)403 get_current_attrib(struct texenv_fragment_program *p, GLuint attrib)
404 {
405 return load_state_var(p, STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED,
406 attrib, 0, 0,
407 glsl_vec4_type());
408 }
409
410 static nir_def *
get_gl_Color(struct texenv_fragment_program * p)411 get_gl_Color(struct texenv_fragment_program *p)
412 {
413 if (p->state->inputs_available & VARYING_BIT_COL0) {
414 return load_input(p, VARYING_SLOT_COL0, glsl_vec4_type());
415 } else {
416 return get_current_attrib(p, VERT_ATTRIB_COLOR0);
417 }
418 }
419
420 static nir_def *
get_source(struct texenv_fragment_program * p,GLuint src,GLuint unit)421 get_source(struct texenv_fragment_program *p,
422 GLuint src, GLuint unit)
423 {
424 switch (src) {
425 case TEXENV_SRC_TEXTURE:
426 return p->src_texture[unit];
427
428 case TEXENV_SRC_TEXTURE0:
429 case TEXENV_SRC_TEXTURE1:
430 case TEXENV_SRC_TEXTURE2:
431 case TEXENV_SRC_TEXTURE3:
432 case TEXENV_SRC_TEXTURE4:
433 case TEXENV_SRC_TEXTURE5:
434 case TEXENV_SRC_TEXTURE6:
435 case TEXENV_SRC_TEXTURE7:
436 return p->src_texture[src - TEXENV_SRC_TEXTURE0];
437
438 case TEXENV_SRC_CONSTANT:
439 return load_state_var(p, STATE_TEXENV_COLOR,
440 unit, 0, 0,
441 glsl_vec4_type());
442
443 case TEXENV_SRC_PRIMARY_COLOR:
444 return get_gl_Color(p);
445
446 case TEXENV_SRC_ZERO:
447 return nir_imm_zero(p->b, 4, 32);
448
449 case TEXENV_SRC_ONE:
450 return nir_imm_vec4(p->b, 1.0f, 1.0f, 1.0f, 1.0f);
451
452 case TEXENV_SRC_PREVIOUS:
453 if (!p->src_previous) {
454 return get_gl_Color(p);
455 } else {
456 return p->src_previous;
457 }
458
459 default:
460 assert(0);
461 return NULL;
462 }
463 }
464
465 static nir_def *
emit_combine_source(struct texenv_fragment_program * p,GLuint unit,GLuint source,GLuint operand)466 emit_combine_source(struct texenv_fragment_program *p,
467 GLuint unit,
468 GLuint source,
469 GLuint operand)
470 {
471 nir_def *src;
472
473 src = get_source(p, source, unit);
474
475 switch (operand) {
476 case TEXENV_OPR_ONE_MINUS_COLOR:
477 return nir_fsub_imm(p->b, 1.0, src);
478
479 case TEXENV_OPR_ALPHA:
480 return src->num_components == 1 ? src : nir_channel(p->b, src, 3);
481
482 case TEXENV_OPR_ONE_MINUS_ALPHA: {
483 nir_def *scalar =
484 src->num_components == 1 ? src : nir_channel(p->b, src, 3);
485
486 return nir_fsub_imm(p->b, 1.0, scalar);
487 }
488
489 case TEXENV_OPR_COLOR:
490 return src;
491
492 default:
493 assert(0);
494 return src;
495 }
496 }
497
498 /**
499 * Check if the RGB and Alpha sources and operands match for the given
500 * texture unit's combinder state. When the RGB and A sources and
501 * operands match, we can emit fewer instructions.
502 */
args_match(const struct state_key * key,GLuint unit)503 static GLboolean args_match( const struct state_key *key, GLuint unit )
504 {
505 GLuint i, numArgs = key->unit[unit].NumArgsRGB;
506
507 for (i = 0; i < numArgs; i++) {
508 if (key->unit[unit].ArgsA[i].Source != key->unit[unit].ArgsRGB[i].Source)
509 return GL_FALSE;
510
511 switch (key->unit[unit].ArgsA[i].Operand) {
512 case TEXENV_OPR_ALPHA:
513 switch (key->unit[unit].ArgsRGB[i].Operand) {
514 case TEXENV_OPR_COLOR:
515 case TEXENV_OPR_ALPHA:
516 break;
517 default:
518 return GL_FALSE;
519 }
520 break;
521 case TEXENV_OPR_ONE_MINUS_ALPHA:
522 switch (key->unit[unit].ArgsRGB[i].Operand) {
523 case TEXENV_OPR_ONE_MINUS_COLOR:
524 case TEXENV_OPR_ONE_MINUS_ALPHA:
525 break;
526 default:
527 return GL_FALSE;
528 }
529 break;
530 default:
531 return GL_FALSE; /* impossible */
532 }
533 }
534
535 return GL_TRUE;
536 }
537
538 static nir_def *
smear(nir_builder * b,nir_def * val)539 smear(nir_builder *b, nir_def *val)
540 {
541 if (val->num_components != 1)
542 return val;
543
544 return nir_replicate(b, val, 4);
545 }
546
547 static nir_def *
emit_combine(struct texenv_fragment_program * p,GLuint unit,GLuint nr,GLuint mode,const struct gl_tex_env_argument * opt)548 emit_combine(struct texenv_fragment_program *p,
549 GLuint unit,
550 GLuint nr,
551 GLuint mode,
552 const struct gl_tex_env_argument *opt)
553 {
554 nir_def *src[MAX_COMBINER_TERMS];
555 nir_def *tmp0, *tmp1;
556 GLuint i;
557
558 assert(nr <= MAX_COMBINER_TERMS);
559
560 for (i = 0; i < nr; i++)
561 src[i] = emit_combine_source( p, unit, opt[i].Source, opt[i].Operand );
562
563 switch (mode) {
564 case TEXENV_MODE_REPLACE:
565 return src[0];
566
567 case TEXENV_MODE_MODULATE:
568 return nir_fmul(p->b, src[0], src[1]);
569
570 case TEXENV_MODE_ADD:
571 return nir_fadd(p->b, src[0], src[1]);
572
573 case TEXENV_MODE_ADD_SIGNED:
574 return nir_fadd_imm(p->b, nir_fadd(p->b, src[0], src[1]), -0.5f);
575
576 case TEXENV_MODE_INTERPOLATE:
577 return nir_flrp(p->b, src[1], src[0], src[2]);
578
579 case TEXENV_MODE_SUBTRACT:
580 return nir_fsub(p->b, src[0], src[1]);
581
582 case TEXENV_MODE_DOT3_RGBA:
583 case TEXENV_MODE_DOT3_RGBA_EXT:
584 case TEXENV_MODE_DOT3_RGB_EXT:
585 case TEXENV_MODE_DOT3_RGB:
586 tmp0 = nir_fadd_imm(p->b, nir_fmul_imm(p->b, src[0], 2.0f), -1.0f);
587 tmp1 = nir_fadd_imm(p->b, nir_fmul_imm(p->b, src[1], 2.0f), -1.0f);
588 return nir_fdot3(p->b, smear(p->b, tmp0), smear(p->b, tmp1));
589
590 case TEXENV_MODE_MODULATE_ADD_ATI:
591 return nir_fmad(p->b, src[0], src[2], src[1]);
592
593 case TEXENV_MODE_MODULATE_SIGNED_ADD_ATI:
594 return nir_fadd_imm(p->b,
595 nir_fadd(p->b,
596 nir_fmul(p->b, src[0], src[2]),
597 src[1]),
598 -0.5f);
599
600 case TEXENV_MODE_MODULATE_SUBTRACT_ATI:
601 return nir_fsub(p->b, nir_fmul(p->b, src[0], src[2]), src[1]);
602
603 case TEXENV_MODE_ADD_PRODUCTS_NV:
604 return nir_fadd(p->b, nir_fmul(p->b, src[0], src[1]),
605 nir_fmul(p->b, src[2], src[3]));
606
607 case TEXENV_MODE_ADD_PRODUCTS_SIGNED_NV:
608 return nir_fadd_imm(p->b,
609 nir_fadd(p->b,
610 nir_fmul(p->b, src[0], src[1]),
611 nir_fmul(p->b, src[2], src[3])),
612 -0.5f);
613 default:
614 assert(0);
615 return src[0];
616 }
617 }
618
619 /**
620 * Generate instructions for one texture unit's env/combiner mode.
621 */
622 static nir_def *
emit_texenv(struct texenv_fragment_program * p,GLuint unit)623 emit_texenv(struct texenv_fragment_program *p, GLuint unit)
624 {
625 const struct state_key *key = p->state;
626 GLboolean rgb_saturate, alpha_saturate;
627 GLuint rgb_shift, alpha_shift;
628
629 if (!key->unit[unit].enabled) {
630 return get_source(p, TEXENV_SRC_PREVIOUS, 0);
631 }
632
633 switch (key->unit[unit].ModeRGB) {
634 case TEXENV_MODE_DOT3_RGB_EXT:
635 alpha_shift = key->unit[unit].ScaleShiftA;
636 rgb_shift = 0;
637 break;
638 case TEXENV_MODE_DOT3_RGBA_EXT:
639 alpha_shift = 0;
640 rgb_shift = 0;
641 break;
642 default:
643 rgb_shift = key->unit[unit].ScaleShiftRGB;
644 alpha_shift = key->unit[unit].ScaleShiftA;
645 break;
646 }
647
648 /* If we'll do rgb/alpha shifting don't saturate in emit_combine().
649 * We don't want to clamp twice.
650 */
651 if (rgb_shift)
652 rgb_saturate = GL_FALSE; /* saturate after rgb shift */
653 else if (need_saturate(key->unit[unit].ModeRGB))
654 rgb_saturate = GL_TRUE;
655 else
656 rgb_saturate = GL_FALSE;
657
658 if (alpha_shift)
659 alpha_saturate = GL_FALSE; /* saturate after alpha shift */
660 else if (need_saturate(key->unit[unit].ModeA))
661 alpha_saturate = GL_TRUE;
662 else
663 alpha_saturate = GL_FALSE;
664
665 nir_def *val;
666
667 /* Emit the RGB and A combine ops
668 */
669 if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
670 args_match(key, unit)) {
671 val = emit_combine(p, unit,
672 key->unit[unit].NumArgsRGB,
673 key->unit[unit].ModeRGB,
674 key->unit[unit].ArgsRGB);
675 val = smear(p->b, val);
676 if (rgb_saturate)
677 val = nir_fsat(p->b, val);
678 }
679 else if (key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA_EXT ||
680 key->unit[unit].ModeRGB == TEXENV_MODE_DOT3_RGBA) {
681 val = emit_combine(p, unit,
682 key->unit[unit].NumArgsRGB,
683 key->unit[unit].ModeRGB,
684 key->unit[unit].ArgsRGB);
685 val = smear(p->b, val);
686 if (rgb_saturate)
687 val = nir_fsat(p->b, val);
688 }
689 else {
690 /* Need to do something to stop from re-emitting identical
691 * argument calculations here:
692 */
693 val = emit_combine(p, unit,
694 key->unit[unit].NumArgsRGB,
695 key->unit[unit].ModeRGB,
696 key->unit[unit].ArgsRGB);
697 val = smear(p->b, val);
698 if (rgb_saturate)
699 val = nir_fsat(p->b, val);
700 nir_def *rgb = val;
701
702 val = emit_combine(p, unit,
703 key->unit[unit].NumArgsA,
704 key->unit[unit].ModeA,
705 key->unit[unit].ArgsA);
706
707 if (val->num_components != 1)
708 val = nir_channel(p->b, val, 3);
709
710 if (alpha_saturate)
711 val = nir_fsat(p->b, val);
712 nir_def *a = val;
713
714 val = nir_vector_insert_imm(p->b, rgb, a, 3);
715 }
716
717 /* Deal with the final shift:
718 */
719 if (alpha_shift || rgb_shift) {
720 nir_def *shift;
721
722 if (rgb_shift == alpha_shift) {
723 shift = nir_imm_float(p->b, (float)(1 << rgb_shift));
724 }
725 else {
726 shift = nir_imm_vec4(p->b,
727 (float)(1 << rgb_shift),
728 (float)(1 << rgb_shift),
729 (float)(1 << rgb_shift),
730 (float)(1 << alpha_shift));
731 }
732
733 return nir_fsat(p->b, nir_fmul(p->b, val, shift));
734 }
735 else
736 return val;
737 }
738
739
740 /**
741 * Generate instruction for getting a texture source term.
742 */
743 static void
load_texture(struct texenv_fragment_program * p,GLuint unit)744 load_texture(struct texenv_fragment_program *p, GLuint unit)
745 {
746 if (p->src_texture[unit])
747 return;
748
749 const GLuint texTarget = p->state->unit[unit].source_index;
750 nir_def *texcoord;
751
752 if (!(p->state->inputs_available & (VARYING_BIT_TEX0 << unit))) {
753 texcoord = get_current_attrib(p, VERT_ATTRIB_TEX0 + unit);
754 } else {
755 texcoord = load_input(p,
756 VARYING_SLOT_TEX0 + unit,
757 glsl_vec4_type());
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, glsl_vec4_type());
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 const char *name =
919 gl_frag_result_name(FRAG_RESULT_COLOR);
920 nir_variable *var =
921 nir_variable_create(p->b->shader, nir_var_shader_out,
922 glsl_vec4_type(), name);
923
924 var->data.location = FRAG_RESULT_COLOR;
925 var->data.driver_location = p->b->shader->num_outputs++;
926
927 p->b->shader->info.outputs_written |= BITFIELD64_BIT(FRAG_RESULT_COLOR);
928
929 nir_store_var(p->b, var, cf, 0xf);
930 }
931
932 /**
933 * Generate a new fragment program which implements the context's
934 * current texture env/combine mode.
935 */
936 static nir_shader *
create_new_program(struct state_key * key,struct gl_program * program,const nir_shader_compiler_options * options)937 create_new_program(struct state_key *key,
938 struct gl_program *program,
939 const nir_shader_compiler_options *options)
940 {
941 struct texenv_fragment_program p;
942
943 memset(&p, 0, sizeof(p));
944 p.state = key;
945
946 program->Parameters = _mesa_new_parameter_list();
947 p.state_params = _mesa_new_parameter_list();
948
949 nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
950 options,
951 "ff-fs");
952
953 nir_shader *s = b.shader;
954
955 s->info.separate_shader = true;
956 s->info.subgroup_size = SUBGROUP_SIZE_UNIFORM;
957
958 p.b = &b;
959
960 if (key->num_draw_buffers)
961 emit_instructions(&p);
962
963 nir_validate_shader(b.shader, "after generating ff-vertex shader");
964
965 if (key->fog_mode)
966 NIR_PASS(_, b.shader, st_nir_lower_fog, key->fog_mode, p.state_params);
967
968 _mesa_add_separate_state_parameters(program, p.state_params);
969 _mesa_free_parameter_list(p.state_params);
970
971 return s;
972 }
973
974 /**
975 * Return a fragment program which implements the current
976 * fixed-function texture, fog and color-sum operations.
977 */
978 struct gl_program *
_mesa_get_fixed_func_fragment_program(struct gl_context * ctx)979 _mesa_get_fixed_func_fragment_program(struct gl_context *ctx)
980 {
981 struct gl_program *prog;
982 struct state_key key;
983 GLuint keySize;
984
985 keySize = make_state_key(ctx, &key);
986
987 prog = (struct gl_program *)
988 _mesa_search_program_cache(ctx->FragmentProgram.Cache,
989 &key, keySize);
990
991 if (!prog) {
992 prog = ctx->Driver.NewProgram(ctx, MESA_SHADER_FRAGMENT, 0, false);
993 if (!prog)
994 return NULL;
995
996 const struct nir_shader_compiler_options *options =
997 st_get_nir_compiler_options(ctx->st, MESA_SHADER_FRAGMENT);
998
999 nir_shader *s =
1000 create_new_program(&key, prog, options);
1001
1002 prog->state.type = PIPE_SHADER_IR_NIR;
1003 prog->nir = s;
1004
1005 prog->SamplersUsed = s->info.samplers_used[0];
1006
1007 /* default mapping from samplers to texture units */
1008 for (unsigned i = 0; i < MAX_SAMPLERS; i++)
1009 prog->SamplerUnits[i] = i;
1010
1011 st_program_string_notify(ctx, GL_FRAGMENT_PROGRAM_ARB, prog);
1012
1013 _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
1014 &key, keySize, prog);
1015 }
1016
1017 return prog;
1018 }
1019