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