• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 /**
29  * \file ffvertex_prog.c
30  *
31  * Create a vertex program to execute the current fixed function T&L pipeline.
32  * \author Keith Whitwell
33  */
34 
35 
36 #include "main/errors.h"
37 #include "util/glheader.h"
38 #include "main/mtypes.h"
39 #include "main/macros.h"
40 #include "main/enums.h"
41 #include "main/context.h"
42 #include "main/ffvertex_prog.h"
43 #include "program/program.h"
44 #include "program/prog_cache.h"
45 #include "program/prog_statevars.h"
46 #include "util/bitscan.h"
47 
48 #include "state_tracker/st_program.h"
49 #include "state_tracker/st_nir.h"
50 
51 #include "compiler/nir/nir_builder.h"
52 #include "compiler/nir/nir_builtin_builder.h"
53 
54 /** Max of number of lights and texture coord units */
55 #define NUM_UNITS MAX2(MAX_TEXTURE_COORD_UNITS, MAX_LIGHTS)
56 
57 struct state_key {
58    GLbitfield varying_vp_inputs;
59 
60    unsigned fragprog_inputs_read:12;
61 
62    unsigned light_color_material_mask:12;
63    unsigned light_global_enabled:1;
64    unsigned light_local_viewer:1;
65    unsigned light_twoside:1;
66    unsigned material_shininess_is_zero:1;
67    unsigned need_eye_coords:1;
68    unsigned normalize:1;
69    unsigned rescale_normals:1;
70 
71    unsigned fog_distance_mode:2;
72    unsigned separate_specular:1;
73    unsigned point_attenuated:1;
74 
75    struct {
76       unsigned char light_enabled:1;
77       unsigned char light_eyepos3_is_zero:1;
78       unsigned char light_spotcutoff_is_180:1;
79       unsigned char light_attenuated:1;
80       unsigned char texmat_enabled:1;
81       unsigned char coord_replace:1;
82       unsigned char texgen_enabled:1;
83       unsigned char texgen_mode0:4;
84       unsigned char texgen_mode1:4;
85       unsigned char texgen_mode2:4;
86       unsigned char texgen_mode3:4;
87    } unit[NUM_UNITS];
88 };
89 
90 
91 #define TXG_NONE           0
92 #define TXG_OBJ_LINEAR     1
93 #define TXG_EYE_LINEAR     2
94 #define TXG_SPHERE_MAP     3
95 #define TXG_REFLECTION_MAP 4
96 #define TXG_NORMAL_MAP     5
97 
translate_texgen(GLboolean enabled,GLenum mode)98 static GLuint translate_texgen( GLboolean enabled, GLenum mode )
99 {
100    if (!enabled)
101       return TXG_NONE;
102 
103    switch (mode) {
104    case GL_OBJECT_LINEAR: return TXG_OBJ_LINEAR;
105    case GL_EYE_LINEAR: return TXG_EYE_LINEAR;
106    case GL_SPHERE_MAP: return TXG_SPHERE_MAP;
107    case GL_REFLECTION_MAP_NV: return TXG_REFLECTION_MAP;
108    case GL_NORMAL_MAP_NV: return TXG_NORMAL_MAP;
109    default: return TXG_NONE;
110    }
111 }
112 
113 #define FDM_EYE_RADIAL    0
114 #define FDM_EYE_PLANE     1
115 #define FDM_EYE_PLANE_ABS 2
116 #define FDM_FROM_ARRAY    3
117 
translate_fog_distance_mode(GLenum source,GLenum mode)118 static GLuint translate_fog_distance_mode(GLenum source, GLenum mode)
119 {
120    if (source == GL_FRAGMENT_DEPTH_EXT) {
121       switch (mode) {
122       case GL_EYE_RADIAL_NV:
123          return FDM_EYE_RADIAL;
124       case GL_EYE_PLANE:
125          return FDM_EYE_PLANE;
126       default: /* shouldn't happen; fall through to a sensible default */
127       case GL_EYE_PLANE_ABSOLUTE_NV:
128          return FDM_EYE_PLANE_ABS;
129       }
130    } else {
131       return FDM_FROM_ARRAY;
132    }
133 }
134 
check_active_shininess(struct gl_context * ctx,const struct state_key * key,GLuint side)135 static GLboolean check_active_shininess( struct gl_context *ctx,
136                                          const struct state_key *key,
137                                          GLuint side )
138 {
139    GLuint attr = MAT_ATTRIB_FRONT_SHININESS + side;
140 
141    if ((key->varying_vp_inputs & VERT_BIT_COLOR0) &&
142        (key->light_color_material_mask & (1 << attr)))
143       return GL_TRUE;
144 
145    if (key->varying_vp_inputs & VERT_BIT_MAT(attr))
146       return GL_TRUE;
147 
148    if (ctx->Light.Material.Attrib[attr][0] != 0.0F)
149       return GL_TRUE;
150 
151    return GL_FALSE;
152 }
153 
154 
make_state_key(struct gl_context * ctx,struct state_key * key)155 static void make_state_key( struct gl_context *ctx, struct state_key *key )
156 {
157    const struct gl_program *fp = ctx->FragmentProgram._Current;
158    GLbitfield mask;
159 
160    memset(key, 0, sizeof(struct state_key));
161 
162    if (_mesa_hw_select_enabled(ctx)) {
163       /* GL_SELECT mode only need position calculation.
164        * glBegin/End use VERT_BIT_SELECT_RESULT_OFFSET for multi name stack in one draw.
165        * glDrawArrays may also be called without user shader, fallback to FF one.
166        */
167       key->varying_vp_inputs = ctx->VertexProgram._VaryingInputs &
168          (VERT_BIT_POS | VERT_BIT_SELECT_RESULT_OFFSET);
169       return;
170    }
171 
172    /* This now relies on texenvprogram.c being active:
173     */
174    assert(fp);
175 
176    key->need_eye_coords = ctx->_NeedEyeCoords;
177 
178    key->fragprog_inputs_read = fp->info.inputs_read;
179    key->varying_vp_inputs = ctx->VertexProgram._VaryingInputs;
180 
181    if (ctx->RenderMode == GL_FEEDBACK) {
182       /* make sure the vertprog emits color and tex0 */
183       key->fragprog_inputs_read |= (VARYING_BIT_COL0 | VARYING_BIT_TEX0);
184    }
185 
186    if (ctx->Light.Enabled) {
187       key->light_global_enabled = 1;
188 
189       if (ctx->Light.Model.LocalViewer)
190           key->light_local_viewer = 1;
191 
192       if (ctx->Light.Model.TwoSide)
193           key->light_twoside = 1;
194 
195       if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
196          key->separate_specular = 1;
197 
198       if (ctx->Light.ColorMaterialEnabled) {
199           key->light_color_material_mask = ctx->Light._ColorMaterialBitmask;
200       }
201 
202       mask = ctx->Light._EnabledLights;
203       while (mask) {
204          const int i = u_bit_scan(&mask);
205          struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
206 
207          key->unit[i].light_enabled = 1;
208 
209          if (lu->EyePosition[3] == 0.0F)
210             key->unit[i].light_eyepos3_is_zero = 1;
211 
212          if (lu->SpotCutoff == 180.0F)
213             key->unit[i].light_spotcutoff_is_180 = 1;
214 
215          if (lu->ConstantAttenuation != 1.0F ||
216              lu->LinearAttenuation != 0.0F ||
217              lu->QuadraticAttenuation != 0.0F)
218             key->unit[i].light_attenuated = 1;
219       }
220 
221       if (check_active_shininess(ctx, key, 0)) {
222          key->material_shininess_is_zero = 0;
223       }
224       else if (key->light_twoside &&
225                check_active_shininess(ctx, key, 1)) {
226          key->material_shininess_is_zero = 0;
227       }
228       else {
229          key->material_shininess_is_zero = 1;
230       }
231    }
232 
233    if (ctx->Transform.Normalize)
234       key->normalize = 1;
235 
236    if (ctx->Transform.RescaleNormals)
237       key->rescale_normals = 1;
238 
239    /* Only distinguish fog parameters if we actually need */
240    if (key->fragprog_inputs_read & VARYING_BIT_FOGC)
241       key->fog_distance_mode =
242          translate_fog_distance_mode(ctx->Fog.FogCoordinateSource,
243                                      ctx->Fog.FogDistanceMode);
244 
245    if (ctx->Point._Attenuated)
246       key->point_attenuated = 1;
247 
248    mask = ctx->Texture._EnabledCoordUnits | ctx->Texture._TexGenEnabled
249       | ctx->Texture._TexMatEnabled | ctx->Point.CoordReplace;
250    while (mask) {
251       const int i = u_bit_scan(&mask);
252       struct gl_fixedfunc_texture_unit *texUnit =
253          &ctx->Texture.FixedFuncUnit[i];
254 
255       if (ctx->Point.PointSprite)
256          if (ctx->Point.CoordReplace & (1u << i))
257             key->unit[i].coord_replace = 1;
258 
259       if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
260          key->unit[i].texmat_enabled = 1;
261 
262       if (texUnit->TexGenEnabled) {
263          key->unit[i].texgen_enabled = 1;
264 
265          key->unit[i].texgen_mode0 =
266             translate_texgen( texUnit->TexGenEnabled & (1<<0),
267                               texUnit->GenS.Mode );
268          key->unit[i].texgen_mode1 =
269             translate_texgen( texUnit->TexGenEnabled & (1<<1),
270                               texUnit->GenT.Mode );
271          key->unit[i].texgen_mode2 =
272             translate_texgen( texUnit->TexGenEnabled & (1<<2),
273                               texUnit->GenR.Mode );
274          key->unit[i].texgen_mode3 =
275             translate_texgen( texUnit->TexGenEnabled & (1<<3),
276                               texUnit->GenQ.Mode );
277       }
278    }
279 }
280 
281 struct tnl_program {
282    const struct state_key *state;
283    struct gl_program_parameter_list *state_params;
284    GLboolean mvp_with_dp4;
285 
286    nir_builder *b;
287 
288    nir_def *eye_position;
289    nir_def *eye_position_z;
290    nir_def *eye_position_normalized;
291    nir_def *transformed_normal;
292 
293    GLuint materials;
294    GLuint color_materials;
295 };
296 
297 static nir_variable *
register_state_var(struct tnl_program * p,gl_state_index16 s0,gl_state_index16 s1,gl_state_index16 s2,gl_state_index16 s3,const struct glsl_type * type)298 register_state_var(struct tnl_program *p,
299                    gl_state_index16 s0,
300                    gl_state_index16 s1,
301                    gl_state_index16 s2,
302                    gl_state_index16 s3,
303                    const struct glsl_type *type)
304 {
305    gl_state_index16 tokens[STATE_LENGTH];
306    tokens[0] = s0;
307    tokens[1] = s1;
308    tokens[2] = s2;
309    tokens[3] = s3;
310    nir_variable *var = nir_find_state_variable(p->b->shader, tokens);
311    if (var)
312       return var;
313 
314    var = st_nir_state_variable_create(p->b->shader, type, tokens);
315    var->data.driver_location = _mesa_add_state_reference(p->state_params, tokens);
316 
317    return var;
318 }
319 
320 static nir_def *
load_state_var(struct tnl_program * p,gl_state_index16 s0,gl_state_index16 s1,gl_state_index16 s2,gl_state_index16 s3,const struct glsl_type * type)321 load_state_var(struct tnl_program *p,
322                gl_state_index16 s0,
323                gl_state_index16 s1,
324                gl_state_index16 s2,
325                gl_state_index16 s3,
326                const struct glsl_type *type)
327 {
328    nir_variable *var = register_state_var(p, s0, s1, s2, s3, type);
329    return nir_load_var(p->b, var);
330 }
331 
332 static nir_def *
load_state_vec4(struct tnl_program * p,gl_state_index16 s0,gl_state_index16 s1,gl_state_index16 s2,gl_state_index16 s3)333 load_state_vec4(struct tnl_program *p,
334                 gl_state_index16 s0,
335                 gl_state_index16 s1,
336                 gl_state_index16 s2,
337                 gl_state_index16 s3)
338 {
339    return load_state_var(p, s0, s1, s2, s3, glsl_vec4_type());
340 }
341 
342 static void
load_state_mat4(struct tnl_program * p,nir_def * out[4],gl_state_index state_index,unsigned tex_index)343 load_state_mat4(struct tnl_program *p, nir_def *out[4],
344                 gl_state_index state_index, unsigned tex_index)
345 {
346    for (int i = 0; i < 4; ++i)
347       out[i] = load_state_vec4(p, state_index, tex_index, i, i);
348 }
349 
350 static nir_def *
load_input(struct tnl_program * p,gl_vert_attrib attr,unsigned num_components)351 load_input(struct tnl_program *p, gl_vert_attrib attr, unsigned num_components)
352 {
353    if (p->state->varying_vp_inputs & VERT_BIT(attr)) {
354       return nir_load_input(p->b, num_components, 32, nir_imm_int(p->b, 0),
355                             .io_semantics.location = attr);
356    } else {
357       return load_state_var(p, STATE_CURRENT_ATTRIB, attr, 0, 0,
358                             glsl_vector_type(GLSL_TYPE_FLOAT, num_components));
359    }
360 }
361 
362 static nir_def *
load_input_vec4(struct tnl_program * p,gl_vert_attrib attr)363 load_input_vec4(struct tnl_program *p, gl_vert_attrib attr)
364 {
365    return load_input(p, attr, 4);
366 }
367 
368 static nir_variable *
register_output(struct tnl_program * p,gl_varying_slot slot,const struct glsl_type * type)369 register_output(struct tnl_program *p, gl_varying_slot slot,
370                 const struct glsl_type *type)
371 {
372    nir_variable *var = nir_get_variable_with_location(p->b->shader, nir_var_shader_out,
373                                                       slot, type);
374    p->b->shader->info.outputs_written |= BITFIELD64_BIT(slot);
375    return var;
376 }
377 
378 static void
store_output_vec4_masked(struct tnl_program * p,gl_varying_slot slot,nir_def * value,unsigned writemask)379 store_output_vec4_masked(struct tnl_program *p, gl_varying_slot slot, nir_def *value,
380                          unsigned writemask)
381 {
382    assert(writemask <= 0xf);
383    nir_store_output(p->b, value, nir_imm_int(p->b, 0),
384                     .write_mask = writemask,
385                     .io_semantics.location = slot);
386 }
387 
388 static void
store_output_vec4(struct tnl_program * p,gl_varying_slot slot,nir_def * value)389 store_output_vec4(struct tnl_program *p, gl_varying_slot slot,
390                   nir_def *value)
391 {
392    store_output_vec4_masked(p, slot, value, 0xf);
393 }
394 
395 static void
store_output_float(struct tnl_program * p,gl_varying_slot slot,nir_def * value)396 store_output_float(struct tnl_program *p, gl_varying_slot slot,
397                    nir_def *value)
398 {
399    store_output_vec4_masked(p, slot, value, 0x1);
400 }
401 
402 
403 static nir_def *
emit_matrix_transform_vec4(nir_builder * b,nir_def * mat[4],nir_def * src)404 emit_matrix_transform_vec4(nir_builder *b,
405                            nir_def *mat[4],
406                            nir_def *src)
407 {
408    return nir_vec4(b,
409                    nir_fdot4(b, src, mat[0]),
410                    nir_fdot4(b, src, mat[1]),
411                    nir_fdot4(b, src, mat[2]),
412                    nir_fdot4(b, src, mat[3]));
413 }
414 
415 static nir_def *
emit_transpose_matrix_transform_vec4(nir_builder * b,nir_def * mat[4],nir_def * src)416 emit_transpose_matrix_transform_vec4(nir_builder *b,
417                                      nir_def *mat[4],
418                                      nir_def *src)
419 {
420    nir_def *result;
421    result = nir_fmul(b, nir_channel(b, src, 0), mat[0]);
422    result = nir_fmad(b, nir_channel(b, src, 1), mat[1], result);
423    result = nir_fmad(b, nir_channel(b, src, 2), mat[2], result);
424    result = nir_fmad(b, nir_channel(b, src, 3), mat[3], result);
425    return result;
426 }
427 
428 static nir_def *
emit_matrix_transform_vec3(nir_builder * b,nir_def * mat[3],nir_def * src)429 emit_matrix_transform_vec3(nir_builder *b,
430                            nir_def *mat[3],
431                            nir_def *src)
432 {
433    return nir_vec3(b,
434                    nir_fdot3(b, src, mat[0]),
435                    nir_fdot3(b, src, mat[1]),
436                    nir_fdot3(b, src, mat[2]));
437 }
438 
439 static nir_def *
emit_normalize_vec3(nir_builder * b,nir_def * src)440 emit_normalize_vec3(nir_builder *b, nir_def *src)
441 {
442    nir_def *tmp = nir_frsq(b, nir_fdot3(b, src, src));
443    return nir_fmul(b, src, tmp);
444 }
445 
446 static void
emit_passthrough(struct tnl_program * p,gl_vert_attrib attr,gl_varying_slot varying)447 emit_passthrough(struct tnl_program *p, gl_vert_attrib attr,
448                  gl_varying_slot varying)
449 {
450    nir_def *val = load_input_vec4(p, attr);
451    store_output_vec4(p, varying, val);
452 }
453 
454 static nir_def *
get_eye_position(struct tnl_program * p)455 get_eye_position(struct tnl_program *p)
456 {
457    if (!p->eye_position) {
458       nir_def *pos =
459          load_input_vec4(p, VERT_ATTRIB_POS);
460       if (p->mvp_with_dp4) {
461          nir_def *modelview[4];
462          load_state_mat4(p, modelview, STATE_MODELVIEW_MATRIX, 0);
463          p->eye_position =
464             emit_matrix_transform_vec4(p->b, modelview, pos);
465       } else {
466          nir_def *modelview[4];
467          load_state_mat4(p, modelview,
468                          STATE_MODELVIEW_MATRIX_TRANSPOSE, 0);
469          p->eye_position =
470             emit_transpose_matrix_transform_vec4(p->b, modelview, pos);
471       }
472    }
473 
474    return p->eye_position;
475 }
476 
477 static nir_def *
get_eye_position_z(struct tnl_program * p)478 get_eye_position_z(struct tnl_program *p)
479 {
480    return nir_channel(p->b, get_eye_position(p), 2);
481 }
482 
483 static nir_def *
get_eye_position_normalized(struct tnl_program * p)484 get_eye_position_normalized(struct tnl_program *p)
485 {
486    if (!p->eye_position_normalized) {
487       nir_def *eye = get_eye_position(p);
488       p->eye_position_normalized = emit_normalize_vec3(p->b, eye);
489    }
490 
491    return p->eye_position_normalized;
492 }
493 
494 static nir_def *
get_transformed_normal(struct tnl_program * p)495 get_transformed_normal(struct tnl_program *p)
496 {
497    if (!p->transformed_normal &&
498        !p->state->need_eye_coords &&
499        !p->state->normalize &&
500        !(p->state->need_eye_coords == p->state->rescale_normals)) {
501       p->transformed_normal = load_input(p, VERT_ATTRIB_NORMAL, 3);
502    } else if (!p->transformed_normal) {
503       nir_def *normal = load_input(p, VERT_ATTRIB_NORMAL, 3);
504 
505       if (p->state->need_eye_coords) {
506          nir_def *mvinv[4];
507          load_state_mat4(p, mvinv, STATE_MODELVIEW_MATRIX_INVTRANS, 0);
508          normal = emit_matrix_transform_vec3(p->b, mvinv, normal);
509       }
510 
511       /* Normalize/Rescale:
512        */
513       if (p->state->normalize)
514          normal = emit_normalize_vec3(p->b, normal);
515       else if (p->state->need_eye_coords == p->state->rescale_normals) {
516          nir_def *scale =
517             load_state_var(p, STATE_NORMAL_SCALE, 0, 0, 0,
518                            glsl_float_type());
519          normal = nir_fmul(p->b, normal, scale);
520       }
521 
522       p->transformed_normal = normal;
523    }
524 
525    return p->transformed_normal;
526 }
527 
material_attrib(GLuint side,GLuint property)528 static GLuint material_attrib( GLuint side, GLuint property )
529 {
530    switch (property) {
531    case STATE_AMBIENT:
532       return MAT_ATTRIB_FRONT_AMBIENT + side;
533    case STATE_DIFFUSE:
534       return MAT_ATTRIB_FRONT_DIFFUSE + side;
535    case STATE_SPECULAR:
536       return MAT_ATTRIB_FRONT_SPECULAR + side;
537    case STATE_EMISSION:
538       return MAT_ATTRIB_FRONT_EMISSION + side;
539    case STATE_SHININESS:
540       return MAT_ATTRIB_FRONT_SHININESS + side;
541    default:
542       unreachable("invalid value");
543    }
544 }
545 
546 
547 /**
548  * Get a bitmask of which material values vary on a per-vertex basis.
549  */
set_material_flags(struct tnl_program * p)550 static void set_material_flags( struct tnl_program *p )
551 {
552    p->color_materials = 0;
553    p->materials = 0;
554 
555    if (p->state->varying_vp_inputs & VERT_BIT_COLOR0) {
556       p->materials =
557          p->color_materials = p->state->light_color_material_mask;
558    }
559 
560    p->materials |= ((p->state->varying_vp_inputs & VERT_BIT_MAT_ALL)
561                     >> VERT_ATTRIB_MAT(0));
562 }
563 
564 
565 static nir_def *
get_material(struct tnl_program * p,GLuint side,GLuint property)566 get_material(struct tnl_program *p, GLuint side,
567              GLuint property)
568 {
569    GLuint attrib = material_attrib(side, property);
570 
571    if (p->color_materials & (1<<attrib))
572       return load_input_vec4(p, VERT_ATTRIB_COLOR0);
573    else if (p->materials & (1<<attrib)) {
574       /* Put material values in the GENERIC slots -- they are not used
575        * for anything in fixed function mode.
576        */
577       return load_input_vec4(p, VERT_ATTRIB_MAT(attrib));
578    } else {
579       return load_state_vec4(p, STATE_MATERIAL, attrib, 0, 0);
580    }
581 }
582 
583 #define SCENE_COLOR_BITS(side) (( MAT_BIT_FRONT_EMISSION | \
584                                   MAT_BIT_FRONT_AMBIENT | \
585                                   MAT_BIT_FRONT_DIFFUSE) << (side))
586 
587 
588 /**
589  * Either return a precalculated constant value or emit code to
590  * calculate these values dynamically in the case where material calls
591  * are present between begin/end pairs.
592  *
593  * Probably want to shift this to the program compilation phase - if
594  * we always emitted the calculation here, a smart compiler could
595  * detect that it was constant (given a certain set of inputs), and
596  * lift it out of the main loop.  That way the programs created here
597  * would be independent of the vertex_buffer details.
598  */
599 static nir_def *
get_scenecolor(struct tnl_program * p,GLuint side)600 get_scenecolor(struct tnl_program *p, GLuint side)
601 {
602    if (p->materials & SCENE_COLOR_BITS(side)) {
603       nir_def *lm_ambient =
604          load_state_vec4(p, STATE_LIGHTMODEL_AMBIENT, 0, 0, 0);
605       nir_def *material_emission =
606          get_material(p, side, STATE_EMISSION);
607       nir_def *material_ambient =
608          get_material(p, side, STATE_AMBIENT);
609       nir_def *material_diffuse =
610          get_material(p, side, STATE_DIFFUSE);
611 
612       // rgb: material_emission + material_ambient * lm_ambient
613       // alpha: material_diffuse.a
614       return nir_vector_insert_imm(p->b, nir_fmad(p->b,
615                                                   lm_ambient,
616                                                   material_ambient,
617                                                   material_emission),
618                                    nir_channel(p->b,
619                                                material_diffuse,
620                                                3),
621                                    3);
622    }
623    else
624       return load_state_vec4(p, STATE_LIGHTMODEL_SCENECOLOR, side, 0, 0);
625 }
626 
627 static nir_def *
get_lightprod(struct tnl_program * p,GLuint light,GLuint side,GLuint property,bool * is_state_light)628 get_lightprod(struct tnl_program *p, GLuint light,
629               GLuint side, GLuint property, bool *is_state_light)
630 {
631    GLuint attrib = material_attrib(side, property);
632    if (p->materials & (1<<attrib)) {
633       *is_state_light = true;
634       return load_state_vec4(p, STATE_LIGHT, light, property, 0);
635    } else {
636       *is_state_light = false;
637       return load_state_vec4(p, STATE_LIGHTPROD, light, attrib, 0);
638    }
639 }
640 
641 
642 static nir_def *
calculate_light_attenuation(struct tnl_program * p,GLuint i,nir_def * VPpli,nir_def * dist)643 calculate_light_attenuation(struct tnl_program *p,
644                             GLuint i,
645                             nir_def *VPpli,
646                             nir_def *dist)
647 {
648    nir_def *attenuation = NULL;
649    nir_def *att = NULL;
650 
651    /* Calculate spot attenuation:
652     */
653    if (!p->state->unit[i].light_spotcutoff_is_180) {
654        nir_def *spot_dir_norm =
655          load_state_vec4(p, STATE_LIGHT_SPOT_DIR_NORMALIZED, i, 0, 0);
656       attenuation =
657          load_state_vec4(p, STATE_LIGHT, i, STATE_ATTENUATION, 0);
658 
659       nir_def *spot = nir_fdot3(p->b, nir_fneg(p->b, VPpli),
660                                     spot_dir_norm);
661       nir_def *cmp = nir_flt(p->b, nir_channel(p->b, spot_dir_norm, 3),
662                                  spot);
663       spot = nir_fpow(p->b, spot, nir_channel(p->b, attenuation, 3));
664       att = nir_bcsel(p->b, cmp, spot, nir_imm_zero(p->b, 1, 32));
665    }
666 
667    /* Calculate distance attenuation(See formula (2.4) at glspec 2.1 page 62):
668     *
669     * Skip the calucation when _dist_ is undefined(light_eyepos3_is_zero)
670     */
671    if (p->state->unit[i].light_attenuated && dist) {
672       if (!attenuation) {
673          attenuation = load_state_vec4(p, STATE_LIGHT, i,
674                                        STATE_ATTENUATION, 0);
675       }
676 
677       /* dist is the reciprocal of ||VP|| used in the distance
678        * attenuation formula. So need to get the reciprocal of dist first
679        * before applying to the formula.
680        */
681       dist = nir_frcp(p->b, dist);
682 
683       /* 1, d, d*d */
684       nir_def *tmp = nir_vec3(p->b,
685          nir_imm_float(p->b, 1.0f),
686          dist,
687          nir_fmul(p->b, dist, dist)
688       );
689       tmp = nir_frcp(p->b, nir_fdot3(p->b, tmp, attenuation));
690 
691       if (!p->state->unit[i].light_spotcutoff_is_180)
692          return nir_fmul(p->b, tmp, att);
693       return tmp;
694    }
695 
696    return att;
697 }
698 
699 static nir_def *
emit_lit(nir_builder * b,nir_def * src)700 emit_lit(nir_builder *b,
701          nir_def *src)
702 {
703    nir_def *zero = nir_imm_zero(b, 1, 32);
704    nir_def *one = nir_imm_float(b, 1.0f);
705    nir_def *src_x = nir_channel(b, src, 0);
706    nir_def *src_y = nir_channel(b, src, 1);
707    nir_def *src_w = nir_channel(b, src, 3);
708 
709    nir_def *wclamp = nir_fmax(b, nir_fmin(b, src_w,
710                                               nir_imm_float(b, 128.0f)),
711                                   nir_imm_float(b, -128.0f));
712    nir_def *pow = nir_fpow(b, nir_fmax(b, src_y, zero), wclamp);
713 
714    return nir_vec4(b,
715                    one,
716                    nir_fmax(b, src_x, zero),
717                    nir_bcsel(b,
718                              nir_fge(b, zero, src_x),
719                              zero,
720                              pow),
721                    one);
722 }
723 
724 /**
725  * Compute:
726  *   lit.y = MAX(0, dots.x)
727  *   lit.z = SLT(0, dots.x)
728  */
729 static nir_def *
emit_degenerate_lit(nir_builder * b,nir_def * dots)730 emit_degenerate_lit(nir_builder *b,
731                     nir_def *dots)
732 {
733    nir_def *id = nir_imm_vec4(b, 0.0f, 0.0f, 0.0f, 1.0f);
734 
735    /* Note that lit.x & lit.w will not be examined.  Note also that
736     * dots.xyzw == dots.xxxx.
737     */
738 
739    nir_def *zero = nir_imm_zero(b, 1, 32);
740    nir_def *dots_x = nir_channel(b, dots, 0);
741    nir_def *tmp = nir_fmax(b, id, dots);
742    return nir_vector_insert_imm(b, tmp, nir_slt(b, zero, dots_x), 2);
743 }
744 
745 
746 /* Need to add some addtional parameters to allow lighting in object
747  * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
748  * space lighting.
749  */
build_lighting(struct tnl_program * p)750 static void build_lighting( struct tnl_program *p )
751 {
752    const GLboolean twoside = p->state->light_twoside;
753    const GLboolean separate = p->state->separate_specular;
754    GLuint nr_lights = 0;
755    nir_def *lit = NULL;
756    nir_def *dots = nir_imm_zero(p->b, 4, 32);
757    nir_def *normal = get_transformed_normal(p);
758    nir_def *_col0 = NULL, *_col1 = NULL;
759    nir_def *_bfc0 = NULL, *_bfc1 = NULL;
760    GLuint i;
761 
762    /*
763     * NOTE:
764     * dots.x = dot(normal, VPpli)
765     * dots.y = dot(normal, halfAngle)
766     * dots.z = back.shininess
767     * dots.w = front.shininess
768     */
769 
770    for (i = 0; i < MAX_LIGHTS; i++)
771       if (p->state->unit[i].light_enabled)
772          nr_lights++;
773 
774    set_material_flags(p);
775 
776    {
777       if (!p->state->material_shininess_is_zero) {
778          nir_def *shininess = get_material(p, 0, STATE_SHININESS);
779          nir_def *tmp = nir_channel(p->b, shininess, 0);
780          dots = nir_vector_insert_imm(p->b, dots, tmp, 3);
781       }
782 
783       _col0 = get_scenecolor(p, 0);
784       if (separate)
785          _col1 = nir_imm_vec4(p->b, 0.0f, 0.0f, 0.0f, 1.0f);
786    }
787 
788    if (twoside) {
789       if (!p->state->material_shininess_is_zero) {
790          /* Note that we negate the back-face specular exponent here.
791           * The negation will be un-done later in the back-face code below.
792           */
793          nir_def *shininess = get_material(p, 1, STATE_SHININESS);
794          nir_def *tmp = nir_channel(p->b, shininess, 0);
795          tmp = nir_fneg(p->b, tmp);
796          dots = nir_vector_insert_imm(p->b, dots, tmp, 2);
797       }
798 
799       _bfc0 = get_scenecolor(p, 1);
800       if (separate)
801          _bfc1 = nir_imm_vec4(p->b, 0.0f, 0.0f, 0.0f, 1.0f);
802    }
803 
804    /* If no lights, still need to emit the scenecolor.
805     */
806    store_output_vec4(p, VARYING_SLOT_COL0, _col0);
807 
808    if (separate)
809       store_output_vec4(p, VARYING_SLOT_COL1, _col1);
810 
811    if (twoside)
812       store_output_vec4(p, VARYING_SLOT_BFC0, _bfc0);
813 
814    if (twoside && separate)
815       store_output_vec4(p, VARYING_SLOT_BFC1, _bfc1);
816 
817    if (nr_lights == 0)
818       return;
819 
820    /* Declare light products first to place them sequentially next to each
821     * other for optimal constant uploads.
822     */
823    nir_def *lightprod_front[MAX_LIGHTS][3];
824    nir_def *lightprod_back[MAX_LIGHTS][3];
825    bool lightprod_front_is_state_light[MAX_LIGHTS][3];
826    bool lightprod_back_is_state_light[MAX_LIGHTS][3];
827 
828    for (i = 0; i < MAX_LIGHTS; i++) {
829       if (p->state->unit[i].light_enabled) {
830          lightprod_front[i][0] = get_lightprod(p, i, 0, STATE_AMBIENT,
831                                                &lightprod_front_is_state_light[i][0]);
832          if (twoside)
833             lightprod_back[i][0] = get_lightprod(p, i, 1, STATE_AMBIENT,
834                                                  &lightprod_back_is_state_light[i][0]);
835 
836          lightprod_front[i][1] = get_lightprod(p, i, 0, STATE_DIFFUSE,
837                                                &lightprod_front_is_state_light[i][1]);
838          if (twoside)
839             lightprod_back[i][1] = get_lightprod(p, i, 1, STATE_DIFFUSE,
840                                                  &lightprod_back_is_state_light[i][1]);
841 
842          lightprod_front[i][2] = get_lightprod(p, i, 0, STATE_SPECULAR,
843                                                &lightprod_front_is_state_light[i][2]);
844          if (twoside)
845             lightprod_back[i][2] = get_lightprod(p, i, 1, STATE_SPECULAR,
846                                                  &lightprod_back_is_state_light[i][2]);
847       }
848    }
849 
850    /* Add more variables now that we'll use later, so that they are nicely
851     * sorted in the parameter list.
852     */
853    for (i = 0; i < MAX_LIGHTS; i++) {
854       if (p->state->unit[i].light_enabled) {
855          if (p->state->unit[i].light_eyepos3_is_zero)
856             register_state_var(p, STATE_LIGHT_POSITION_NORMALIZED,
857                                i, 0, 0,
858                                glsl_vector_type(GLSL_TYPE_FLOAT, 3));
859          else
860             register_state_var(p, STATE_LIGHT_POSITION, i, 0, 0,
861                                glsl_vec4_type());
862       }
863    }
864    for (i = 0; i < MAX_LIGHTS; i++) {
865       if (p->state->unit[i].light_enabled &&
866           (!p->state->unit[i].light_spotcutoff_is_180 ||
867            (p->state->unit[i].light_attenuated &&
868             !p->state->unit[i].light_eyepos3_is_zero)))
869          register_state_var(p, STATE_LIGHT, i, STATE_ATTENUATION, 0,
870                             glsl_vec4_type());
871    }
872 
873    for (i = 0; i < MAX_LIGHTS; i++) {
874       if (p->state->unit[i].light_enabled) {
875          nir_def *half = NULL;
876          nir_def *att = NULL, *VPpli = NULL;
877          nir_def *dist = NULL;
878 
879          if (p->state->unit[i].light_eyepos3_is_zero) {
880             VPpli = load_state_var(p, STATE_LIGHT_POSITION_NORMALIZED,
881                                    i, 0, 0,
882                                    glsl_vector_type(GLSL_TYPE_FLOAT, 3));
883          } else {
884             nir_def *Ppli =
885                load_state_vec4(p, STATE_LIGHT_POSITION, i, 0, 0);
886 
887             nir_def *V = get_eye_position(p);
888             VPpli = nir_fsub(p->b, Ppli, V);
889 
890             /* Normalize VPpli.  The dist value also used in
891              * attenuation below.
892              */
893             dist = nir_frsq(p->b, nir_fdot3(p->b, VPpli, VPpli));
894             VPpli = nir_fmul(p->b, VPpli, dist);
895          }
896 
897          /* Calculate attenuation:
898           */
899          att = calculate_light_attenuation(p, i, VPpli, dist);
900 
901          /* Calculate viewer direction, or use infinite viewer:
902           */
903          if (!p->state->material_shininess_is_zero) {
904             if (p->state->light_local_viewer) {
905                nir_def *eye_hat = get_eye_position_normalized(p);
906                half = emit_normalize_vec3(p->b,
907                                           nir_fsub(p->b, VPpli, eye_hat));
908             } else if (p->state->unit[i].light_eyepos3_is_zero) {
909                half =
910                   load_state_var(p, STATE_LIGHT_HALF_VECTOR,
911                                  i, 0, 0,
912                                  glsl_vector_type(GLSL_TYPE_FLOAT, 3));
913             } else {
914                nir_def *tmp =
915                   nir_fadd(p->b,
916                            VPpli,
917                            nir_imm_vec3(p->b, 0.0f, 0.0f, 1.0f));
918                half = emit_normalize_vec3(p->b, tmp);
919             }
920          }
921 
922          /* Calculate dot products:
923           */
924          nir_def *dot = nir_fdot3(p->b, normal, VPpli);
925          if (p->state->material_shininess_is_zero) {
926             dots = nir_replicate(p->b, dot, 4);
927          } else {
928             dots = nir_vector_insert_imm(p->b, dots, dot, 0);
929             dot = nir_fdot3(p->b, normal, half);
930             dots = nir_vector_insert_imm(p->b, dots, dot, 1);
931          }
932 
933          /* Front face lighting:
934           */
935          {
936             /* Transform STATE_LIGHT into STATE_LIGHTPROD if needed. This isn't done in
937             * get_lightprod to avoid using too many temps.
938             */
939             for (int j = 0; j < 3; j++) {
940                if (lightprod_front_is_state_light[i][j]) {
941                   nir_def *material =
942                      get_material(p, 0, STATE_AMBIENT + j);
943                   lightprod_front[i][j] =
944                      nir_fmul(p->b, lightprod_front[i][j], material);
945                }
946             }
947 
948             nir_def *ambient = lightprod_front[i][0];
949             nir_def *diffuse = lightprod_front[i][1];
950             nir_def *specular = lightprod_front[i][2];
951 
952             if (att) {
953                /* light is attenuated by distance */
954                lit = emit_lit(p->b, dots);
955                lit = nir_fmul(p->b, lit, att);
956                _col0 = nir_fmad(p->b, nir_channel(p->b, lit, 0), ambient, _col0);
957             } else if (!p->state->material_shininess_is_zero) {
958                /* there's a non-zero specular term */
959                lit = emit_lit(p->b, dots);
960                _col0 = nir_fadd(p->b, ambient, _col0);
961             } else {
962                /* no attenutation, no specular */
963                lit = emit_degenerate_lit(p->b, dots);
964                _col0 = nir_fadd(p->b, ambient, _col0);
965             }
966 
967             _col0 = nir_fmad(p->b, nir_channel(p->b, lit, 1),
968                              diffuse, _col0);
969             if (separate)
970                _col1 = nir_fmad(p->b, nir_channel(p->b, lit, 2),
971                                 specular, _col1);
972             else
973                _col0 = nir_fmad(p->b, nir_channel(p->b, lit, 2),
974                                 specular, _col0);
975          }
976          /* Back face lighting:
977           */
978          nir_def *old_dots = dots;
979          if (twoside) {
980             /* Transform STATE_LIGHT into STATE_LIGHTPROD if needed. This isn't done in
981             * get_lightprod to avoid using too many temps.
982             */
983             for (int j = 0; j < 3; j++) {
984                if (lightprod_back_is_state_light[i][j]) {
985                   nir_def *material =
986                      get_material(p, 1, STATE_AMBIENT + j);
987                   lightprod_back[i][j] =
988                      nir_fmul(p->b, lightprod_back[i][j], material);
989                }
990             }
991 
992             nir_def *ambient = lightprod_back[i][0];
993             nir_def *diffuse = lightprod_back[i][1];
994             nir_def *specular = lightprod_back[i][2];
995 
996             /* For the back face we need to negate the X and Y component
997              * dot products.  dots.Z has the negated back-face specular
998              * exponent.  We swizzle that into the W position.  This
999              * negation makes the back-face specular term positive again.
1000              */
1001             unsigned swiz_xywz[] = {0, 1, 3, 2};
1002             nir_def *dots =
1003                nir_fneg(p->b, nir_swizzle(p->b, old_dots, swiz_xywz, 4));
1004 
1005             if (att) {
1006                /* light is attenuated by distance */
1007                lit = emit_lit(p->b, dots);
1008                lit = nir_fmul(p->b, lit, att);
1009                _bfc0 = nir_fmad(p->b, nir_channel(p->b, lit, 0), ambient, _bfc0);
1010             } else if (!p->state->material_shininess_is_zero) {
1011                /* there's a non-zero specular term */
1012                lit = emit_lit(p->b, dots);
1013                _bfc0 = nir_fadd(p->b, ambient, _bfc0);
1014             } else {
1015                /* no attenutation, no specular */
1016                lit = emit_degenerate_lit(p->b, dots);
1017                _bfc0 = nir_fadd(p->b, ambient, _bfc0);
1018             }
1019 
1020             _bfc0 = nir_fmad(p->b, nir_channel(p->b, lit, 1),
1021                              diffuse, _bfc0);
1022             if (separate)
1023                _bfc1 = nir_fmad(p->b, nir_channel(p->b, lit, 2),
1024                                 specular, _bfc1);
1025             else
1026                _bfc0 = nir_fmad(p->b, nir_channel(p->b, lit, 2),
1027                                 specular, _bfc0);
1028          }
1029       }
1030    }
1031 
1032    store_output_vec4_masked(p, VARYING_SLOT_COL0, _col0, 0x7);
1033    if (separate)
1034       store_output_vec4_masked(p, VARYING_SLOT_COL1, _col1, 0x7);
1035 
1036    if (twoside) {
1037       store_output_vec4_masked(p, VARYING_SLOT_BFC0, _bfc0, 0x7);
1038       if (separate)
1039          store_output_vec4_masked(p, VARYING_SLOT_BFC1, _bfc1, 0x7);
1040    }
1041 }
1042 
1043 
build_fog(struct tnl_program * p)1044 static void build_fog( struct tnl_program *p )
1045 {
1046    nir_def *fog;
1047    switch (p->state->fog_distance_mode) {
1048    case FDM_EYE_RADIAL:
1049       /* Z = sqrt(Xe*Xe + Ye*Ye + Ze*Ze) */
1050       fog = nir_fast_length(p->b,
1051                             nir_trim_vector(p->b, get_eye_position(p), 3));
1052       break;
1053    case FDM_EYE_PLANE: /* Z = Ze */
1054       fog = get_eye_position_z(p);
1055       break;
1056    case FDM_EYE_PLANE_ABS: /* Z = abs(Ze) */
1057       fog = nir_fabs(p->b, get_eye_position_z(p));
1058       break;
1059    case FDM_FROM_ARRAY:
1060       fog = load_input(p, VERT_ATTRIB_FOG, 1);
1061       break;
1062    default:
1063       unreachable("Bad fog mode in build_fog()");
1064    }
1065 
1066    store_output_float(p, VARYING_SLOT_FOGC, fog);
1067 }
1068 
1069 
1070 static nir_def *
build_reflect_texgen(struct tnl_program * p)1071 build_reflect_texgen(struct tnl_program *p)
1072 {
1073    nir_def *normal = get_transformed_normal(p);
1074    nir_def *eye_hat = get_eye_position_normalized(p);
1075    /* n.u */
1076    nir_def *tmp = nir_fdot3(p->b, normal, eye_hat);
1077    /* 2n.u */
1078    tmp = nir_fadd(p->b, tmp, tmp);
1079    /* (-2n.u)n + u */
1080    return nir_fmad(p->b, nir_fneg(p->b, tmp), normal, eye_hat);
1081 }
1082 
1083 
1084 static nir_def *
build_sphere_texgen(struct tnl_program * p)1085 build_sphere_texgen(struct tnl_program *p)
1086 {
1087    nir_def *normal = get_transformed_normal(p);
1088    nir_def *eye_hat = get_eye_position_normalized(p);
1089 
1090    /* Could share the above calculations, but it would be
1091     * a fairly odd state for someone to set (both sphere and
1092     * reflection active for different texture coordinate
1093     * components.  Of course - if two texture units enable
1094     * reflect and/or sphere, things start to tilt in favour
1095     * of seperating this out:
1096     */
1097 
1098    /* n.u */
1099    nir_def *tmp = nir_fdot3(p->b, normal, eye_hat);
1100    /* 2n.u */
1101    tmp = nir_fadd(p->b, tmp, tmp);
1102    /* (-2n.u)n + u */
1103    nir_def *r = nir_fmad(p->b, nir_fneg(p->b, tmp), normal, eye_hat);
1104    /* r + 0,0,1 */
1105    tmp = nir_fadd(p->b, r, nir_imm_vec4(p->b, 0.0f, 0.0f, 1.0f, 0.0f));
1106    /* rx^2 + ry^2 + (rz+1)^2 */
1107    tmp = nir_fdot3(p->b, tmp, tmp);
1108    /* 2/m */
1109    tmp = nir_frsq(p->b, tmp);
1110    /* 1/m */
1111    nir_def *inv_m = nir_fmul_imm(p->b, tmp, 0.5f);
1112    /* r/m + 1/2 */
1113    return nir_fmad(p->b, r, inv_m, nir_imm_float(p->b, 0.5f));
1114 }
1115 
build_texture_transform(struct tnl_program * p)1116 static void build_texture_transform( struct tnl_program *p )
1117 {
1118    GLuint i, j;
1119 
1120    for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
1121 
1122       if (!(p->state->fragprog_inputs_read & VARYING_BIT_TEX(i)))
1123          continue;
1124 
1125       if (p->state->unit[i].coord_replace)
1126          continue;
1127 
1128       nir_def *texcoord;
1129       if (p->state->unit[i].texgen_enabled) {
1130          GLuint copy_mask = 0;
1131          GLuint sphere_mask = 0;
1132          GLuint reflect_mask = 0;
1133          GLuint normal_mask = 0;
1134          GLuint modes[4];
1135          nir_def *comps[4];
1136 
1137          modes[0] = p->state->unit[i].texgen_mode0;
1138          modes[1] = p->state->unit[i].texgen_mode1;
1139          modes[2] = p->state->unit[i].texgen_mode2;
1140          modes[3] = p->state->unit[i].texgen_mode3;
1141 
1142          for (j = 0; j < 4; j++) {
1143             switch (modes[j]) {
1144             case TXG_OBJ_LINEAR: {
1145                nir_def *obj = load_input_vec4(p, VERT_ATTRIB_POS);
1146                nir_def *plane =
1147                   load_state_vec4(p, STATE_TEXGEN, i,
1148                                   STATE_TEXGEN_OBJECT_S + j, 0);
1149                comps[j] = nir_fdot4(p->b, obj, plane);
1150                break;
1151             }
1152             case TXG_EYE_LINEAR: {
1153                nir_def *eye = get_eye_position(p);
1154                nir_def *plane =
1155                   load_state_vec4(p, STATE_TEXGEN, i,
1156                                   STATE_TEXGEN_EYE_S + j, 0);
1157                comps[j] = nir_fdot4(p->b, eye, plane);
1158                break;
1159             }
1160             case TXG_SPHERE_MAP:
1161                sphere_mask |= 1u << j;
1162                break;
1163             case TXG_REFLECTION_MAP:
1164                reflect_mask |= 1u << j;
1165                break;
1166             case TXG_NORMAL_MAP:
1167                normal_mask |= 1u << j;
1168                break;
1169             case TXG_NONE:
1170                copy_mask |= 1u << j;
1171             }
1172          }
1173 
1174          if (sphere_mask) {
1175             nir_def *sphere = build_sphere_texgen(p);
1176             for (j = 0; j < 4; j++)
1177                if (sphere_mask & (1 << j))
1178                   comps[j] = nir_channel(p->b, sphere, j);
1179          }
1180 
1181          if (reflect_mask) {
1182             nir_def *reflect = build_reflect_texgen(p);
1183             for (j = 0; j < 4; j++)
1184                if (reflect_mask & (1 << j))
1185                   comps[j] = nir_channel(p->b, reflect, j);
1186          }
1187 
1188          if (normal_mask) {
1189             nir_def *normal = get_transformed_normal(p);
1190             for (j = 0; j < 4; j++)
1191                if (normal_mask & (1 << j))
1192                   comps[j] = nir_channel(p->b, normal, j);
1193          }
1194 
1195          if (copy_mask) {
1196             nir_def *in = load_input_vec4(p, VERT_ATTRIB_TEX0 + i);
1197             for (j = 0; j < 4; j++)
1198                if (copy_mask & (1 << j))
1199                   comps[j] = nir_channel(p->b, in, j);
1200          }
1201 
1202          texcoord = nir_vec(p->b, comps, 4);
1203       } else
1204          texcoord = load_input_vec4(p, VERT_ATTRIB_TEX0 + i);
1205 
1206       if (p->state->unit[i].texmat_enabled) {
1207          nir_def *texmat[4];
1208          if (p->mvp_with_dp4) {
1209             load_state_mat4(p, texmat, STATE_TEXTURE_MATRIX, i);
1210             texcoord =
1211                emit_matrix_transform_vec4(p->b, texmat, texcoord);
1212          } else {
1213             load_state_mat4(p, texmat,
1214                             STATE_TEXTURE_MATRIX_TRANSPOSE, i);
1215             texcoord =
1216                emit_transpose_matrix_transform_vec4(p->b, texmat,
1217                                                       texcoord);
1218          }
1219       }
1220 
1221       store_output_vec4(p, VARYING_SLOT_TEX0 + i, texcoord);
1222    }
1223 }
1224 
1225 
1226 /**
1227  * Point size attenuation computation.
1228  */
build_atten_pointsize(struct tnl_program * p)1229 static void build_atten_pointsize( struct tnl_program *p )
1230 {
1231    nir_def *eye = get_eye_position_z(p);
1232    nir_def *in_size =
1233       load_state_vec4(p, STATE_POINT_SIZE_CLAMPED, 0, 0, 0);
1234    nir_def *att =
1235       load_state_vec4(p, STATE_POINT_ATTENUATION, 0, 0, 0);
1236 
1237    /* dist = |eyez| */
1238    nir_def *dist = nir_fabs(p->b, eye);
1239 
1240    /* p1 + dist * (p2 + dist * p3); */
1241    nir_def *factor = nir_fmad(p->b, dist, nir_channel(p->b, att, 2),
1242                                               nir_channel(p->b, att, 1));
1243    factor = nir_fmad(p->b, dist, factor, nir_channel(p->b, att, 0));
1244 
1245    /* 1 / sqrt(factor) */
1246    factor = nir_frsq(p->b, factor);
1247 
1248    /* pointSize / sqrt(factor) */
1249    nir_def *size = nir_fmul(p->b, factor,
1250                                 nir_channel(p->b, in_size, 0));
1251 
1252 #if 1
1253    /* this is a good place to clamp the point size since there's likely
1254     * no hardware registers to clamp point size at rasterization time.
1255     */
1256    size = nir_fclamp(p->b, size, nir_channel(p->b, in_size, 1),
1257                                  nir_channel(p->b, in_size, 2));
1258 #endif
1259 
1260    store_output_float(p, VARYING_SLOT_PSIZ, size);
1261 }
1262 
1263 
1264 /**
1265  * Pass-though per-vertex point size, from user's point size array.
1266  */
build_array_pointsize(struct tnl_program * p)1267 static void build_array_pointsize( struct tnl_program *p )
1268 {
1269    nir_def *val = load_input(p, VERT_ATTRIB_POINT_SIZE, 1);
1270    store_output_float(p, VARYING_SLOT_PSIZ, val);
1271 }
1272 
1273 
build_tnl_program(struct tnl_program * p)1274 static void build_tnl_program( struct tnl_program *p )
1275 {
1276    /* Emit the program (except for the MVP transform, which is a separate pass) */
1277 
1278    /* Lighting calculations:
1279     */
1280    if (p->state->fragprog_inputs_read &
1281        (VARYING_BIT_COL0 | VARYING_BIT_COL1)) {
1282       if (p->state->light_global_enabled)
1283          build_lighting(p);
1284       else {
1285          if (p->state->fragprog_inputs_read & VARYING_BIT_COL0)
1286             emit_passthrough(p, VERT_ATTRIB_COLOR0, VARYING_SLOT_COL0);
1287 
1288          if (p->state->fragprog_inputs_read & VARYING_BIT_COL1)
1289             emit_passthrough(p, VERT_ATTRIB_COLOR1, VARYING_SLOT_COL1);
1290       }
1291    }
1292 
1293    if (p->state->fragprog_inputs_read & VARYING_BIT_FOGC)
1294       build_fog(p);
1295 
1296    if (p->state->fragprog_inputs_read & VARYING_BITS_TEX_ANY)
1297       build_texture_transform(p);
1298 
1299    if (p->state->point_attenuated)
1300       build_atten_pointsize(p);
1301    else if (p->state->varying_vp_inputs & VERT_BIT_POINT_SIZE)
1302       build_array_pointsize(p);
1303 
1304    if (p->state->varying_vp_inputs & VERT_BIT_SELECT_RESULT_OFFSET)
1305       emit_passthrough(p, VERT_ATTRIB_SELECT_RESULT_OFFSET,
1306                        VARYING_SLOT_VAR0);
1307 }
1308 
1309 
1310 static nir_shader *
create_new_program(const struct state_key * key,struct gl_program * program,GLboolean mvp_with_dp4,const nir_shader_compiler_options * options)1311 create_new_program( const struct state_key *key,
1312                     struct gl_program *program,
1313                     GLboolean mvp_with_dp4,
1314                     const nir_shader_compiler_options *options)
1315 {
1316    struct tnl_program p;
1317 
1318    memset(&p, 0, sizeof(p));
1319    p.state = key;
1320    p.mvp_with_dp4 = mvp_with_dp4;
1321 
1322    program->Parameters = _mesa_new_parameter_list();
1323    p.state_params = _mesa_new_parameter_list();
1324 
1325    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX,
1326                                                   options,
1327                                                   "ff-vs");
1328 
1329    nir_shader *s = b.shader;
1330 
1331    s->info.separate_shader = true;
1332    s->info.io_lowered = true;
1333 
1334    p.b = &b;
1335 
1336    build_tnl_program( &p );
1337 
1338    nir_validate_shader(b.shader, "after generating ff-vertex shader");
1339 
1340    /* Emit the MVP position transformation */
1341    NIR_PASS(_, b.shader, st_nir_lower_position_invariant, mvp_with_dp4, p.state_params);
1342 
1343    _mesa_add_separate_state_parameters(program, p.state_params);
1344    _mesa_free_parameter_list(p.state_params);
1345 
1346    return s;
1347 }
1348 
1349 
1350 /**
1351  * Return a vertex program which implements the current fixed-function
1352  * transform/lighting/texgen operations.
1353  */
1354 struct gl_program *
_mesa_get_fixed_func_vertex_program(struct gl_context * ctx)1355 _mesa_get_fixed_func_vertex_program(struct gl_context *ctx)
1356 {
1357    struct gl_program *prog;
1358    struct state_key key;
1359 
1360    /* We only update ctx->VertexProgram._VaryingInputs when in VP_MODE_FF _VPMode */
1361    assert(VP_MODE_FF == ctx->VertexProgram._VPMode);
1362 
1363    /* Grab all the relevant state and put it in a single structure:
1364     */
1365    make_state_key(ctx, &key);
1366 
1367    /* Look for an already-prepared program for this state:
1368     */
1369    prog = _mesa_search_program_cache(ctx->VertexProgram.Cache, &key,
1370                                      sizeof(key));
1371 
1372    if (!prog) {
1373       /* OK, we'll have to build a new one */
1374       if (0)
1375          printf("Build new TNL program\n");
1376 
1377       prog = ctx->Driver.NewProgram(ctx, MESA_SHADER_VERTEX, 0, false);
1378       if (!prog)
1379          return NULL;
1380 
1381       const struct nir_shader_compiler_options *options =
1382          st_get_nir_compiler_options(ctx->st, MESA_SHADER_VERTEX);
1383 
1384       nir_shader *s =
1385          create_new_program( &key, prog,
1386                              ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS,
1387                              options);
1388 
1389       prog->state.type = PIPE_SHADER_IR_NIR;
1390       prog->nir = s;
1391 
1392       st_program_string_notify(ctx, GL_VERTEX_PROGRAM_ARB, prog);
1393 
1394       _mesa_program_cache_insert(ctx, ctx->VertexProgram.Cache, &key,
1395                                  sizeof(key), prog);
1396    }
1397 
1398    return prog;
1399 }
1400