1 /**************************************************************************
2 *
3 * Copyright 2003 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * State validation for vertex/fragment shaders.
30 * Note that we have to delay most vertex/fragment shader translation
31 * until rendering time since the linkage between the vertex outputs and
32 * fragment inputs can vary depending on the pairing of shaders.
33 *
34 * Authors:
35 * Brian Paul
36 */
37
38
39 #include "main/mtypes.h"
40 #include "main/framebuffer.h"
41 #include "main/state.h"
42 #include "main/texobj.h"
43 #include "main/texstate.h"
44 #include "program/program.h"
45
46 #include "pipe/p_context.h"
47 #include "pipe/p_shader_tokens.h"
48 #include "util/u_simple_shaders.h"
49 #include "cso_cache/cso_context.h"
50 #include "util/u_debug.h"
51
52 #include "st_context.h"
53 #include "st_atom.h"
54 #include "st_program.h"
55 #include "st_texture.h"
56 #include "st_util.h"
57
58
59 static unsigned
get_texture_index(struct gl_context * ctx,const unsigned unit)60 get_texture_index(struct gl_context *ctx, const unsigned unit)
61 {
62 struct gl_texture_object *texObj = _mesa_get_tex_unit(ctx, unit)->_Current;
63 gl_texture_index index;
64
65 if (texObj) {
66 index = _mesa_tex_target_to_index(ctx, texObj->Target);
67 } else {
68 /* fallback for missing texture */
69 index = TEXTURE_2D_INDEX;
70 }
71
72 return index;
73 }
74
75
76 static inline GLboolean
is_wrap_gl_clamp(GLint param)77 is_wrap_gl_clamp(GLint param)
78 {
79 return param == GL_CLAMP || param == GL_MIRROR_CLAMP_EXT;
80 }
81
82 static void
update_gl_clamp(struct st_context * st,struct gl_program * prog,uint32_t * gl_clamp)83 update_gl_clamp(struct st_context *st, struct gl_program *prog, uint32_t *gl_clamp)
84 {
85 if (!st->emulate_gl_clamp)
86 return;
87
88 gl_clamp[0] = gl_clamp[1] = gl_clamp[2] = 0;
89 GLbitfield samplers_used = prog->SamplersUsed;
90 unsigned unit;
91 /* same as st_atom_sampler.c */
92 for (unit = 0; samplers_used; unit++, samplers_used >>= 1) {
93 unsigned tex_unit = prog->SamplerUnits[unit];
94 if (samplers_used & 1 &&
95 (st->ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER ||
96 st->texture_buffer_sampler)) {
97 const struct gl_texture_object *texobj;
98 struct gl_context *ctx = st->ctx;
99 const struct gl_sampler_object *msamp;
100
101 texobj = ctx->Texture.Unit[tex_unit]._Current;
102 assert(texobj);
103
104 msamp = _mesa_get_samplerobj(ctx, tex_unit);
105 if (is_wrap_gl_clamp(msamp->Attrib.WrapS))
106 gl_clamp[0] |= BITFIELD64_BIT(unit);
107 if (is_wrap_gl_clamp(msamp->Attrib.WrapT))
108 gl_clamp[1] |= BITFIELD64_BIT(unit);
109 if (is_wrap_gl_clamp(msamp->Attrib.WrapR))
110 gl_clamp[2] |= BITFIELD64_BIT(unit);
111 }
112 }
113 }
114
115 /**
116 * Update fragment program state/atom. This involves translating the
117 * Mesa fragment program into a gallium fragment program and binding it.
118 */
119 void
st_update_fp(struct st_context * st)120 st_update_fp( struct st_context *st )
121 {
122 struct st_program *stfp;
123
124 assert(st->ctx->FragmentProgram._Current);
125 stfp = st_program(st->ctx->FragmentProgram._Current);
126 assert(stfp->Base.Target == GL_FRAGMENT_PROGRAM_ARB);
127
128 void *shader;
129
130 if (st->shader_has_one_variant[MESA_SHADER_FRAGMENT] &&
131 !stfp->ati_fs && /* ATI_fragment_shader always has multiple variants */
132 !stfp->Base.ExternalSamplersUsed /* external samplers need variants */) {
133 shader = stfp->variants->driver_shader;
134 } else {
135 struct st_fp_variant_key key;
136
137 /* use memset, not an initializer to be sure all memory is zeroed */
138 memset(&key, 0, sizeof(key));
139
140 key.st = st->has_shareable_shaders ? NULL : st;
141
142 key.lower_flatshade = st->lower_flatshade &&
143 st->ctx->Light.ShadeModel == GL_FLAT;
144
145 /* _NEW_COLOR */
146 key.lower_alpha_func = COMPARE_FUNC_ALWAYS;
147 if (st->lower_alpha_test && _mesa_is_alpha_test_enabled(st->ctx))
148 key.lower_alpha_func = st->ctx->Color.AlphaFunc;
149
150 /* _NEW_LIGHT_STATE | _NEW_PROGRAM */
151 key.lower_two_sided_color = st->lower_two_sided_color &&
152 _mesa_vertex_program_two_side_enabled(st->ctx);
153
154 /* _NEW_POINT | _NEW_PROGRAM */
155 if (st->lower_texcoord_replace && st->ctx->Point.PointSprite &&
156 st->ctx->Point.CoordReplace)
157 key.lower_texcoord_replace = st->ctx->Point.CoordReplace;
158
159 /* gl_driver_flags::NewFragClamp */
160 key.clamp_color = st->clamp_frag_color_in_shader &&
161 st->ctx->Color._ClampFragmentColor;
162
163 /* _NEW_MULTISAMPLE | _NEW_BUFFERS */
164 key.persample_shading =
165 st->force_persample_in_shader &&
166 _mesa_is_multisample_enabled(st->ctx) &&
167 st->ctx->Multisample.SampleShading &&
168 st->ctx->Multisample.MinSampleShadingValue *
169 _mesa_geometric_samples(st->ctx->DrawBuffer) > 1;
170
171 key.lower_depth_clamp =
172 st->clamp_frag_depth_in_shader &&
173 (st->ctx->Transform.DepthClampNear ||
174 st->ctx->Transform.DepthClampFar);
175
176 if (stfp->ati_fs) {
177 key.fog = st->ctx->Fog._PackedEnabledMode;
178
179 for (unsigned u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) {
180 key.texture_index[u] = get_texture_index(st->ctx, u);
181 }
182 }
183
184 key.external = st_get_external_sampler_key(st, &stfp->Base);
185 update_gl_clamp(st, st->ctx->FragmentProgram._Current, key.gl_clamp);
186
187 simple_mtx_lock(&st->ctx->Shared->Mutex);
188 shader = st_get_fp_variant(st, stfp, &key)->base.driver_shader;
189 simple_mtx_unlock(&st->ctx->Shared->Mutex);
190 }
191
192 st_reference_prog(st, &st->fp, stfp);
193
194 cso_set_fragment_shader_handle(st->cso_context, shader);
195 }
196
197
198 /**
199 * Update vertex program state/atom. This involves translating the
200 * Mesa vertex program into a gallium fragment program and binding it.
201 */
202 void
st_update_vp(struct st_context * st)203 st_update_vp( struct st_context *st )
204 {
205 struct st_program *stvp;
206
207 /* find active shader and params -- Should be covered by
208 * ST_NEW_VERTEX_PROGRAM
209 */
210 assert(st->ctx->VertexProgram._Current);
211 stvp = st_program(st->ctx->VertexProgram._Current);
212 assert(stvp->Base.Target == GL_VERTEX_PROGRAM_ARB);
213
214 if (st->shader_has_one_variant[MESA_SHADER_VERTEX] &&
215 !st->vertdata_edgeflags) {
216 st->vp_variant = st_common_variant(stvp->variants);
217 } else {
218 struct st_common_variant_key key;
219
220 memset(&key, 0, sizeof(key));
221
222 key.st = st->has_shareable_shaders ? NULL : st;
223
224 /* When this is true, we will add an extra input to the vertex
225 * shader translation (for edgeflags), an extra output with
226 * edgeflag semantics, and extend the vertex shader to pass through
227 * the input to the output. We'll need to use similar logic to set
228 * up the extra vertex_element input for edgeflags.
229 */
230 key.passthrough_edgeflags = st->vertdata_edgeflags;
231
232 key.clamp_color = st->clamp_vert_color_in_shader &&
233 st->ctx->Light._ClampVertexColor &&
234 (stvp->Base.info.outputs_written &
235 (VARYING_SLOT_COL0 |
236 VARYING_SLOT_COL1 |
237 VARYING_SLOT_BFC0 |
238 VARYING_SLOT_BFC1));
239
240 key.lower_depth_clamp =
241 !st->gp && !st->tep &&
242 st->clamp_frag_depth_in_shader &&
243 (st->ctx->Transform.DepthClampNear ||
244 st->ctx->Transform.DepthClampFar);
245
246 if (key.lower_depth_clamp)
247 key.clip_negative_one_to_one =
248 st->ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE;
249
250 if (!st->ctx->GeometryProgram._Current &&
251 !st->ctx->TessEvalProgram._Current) {
252 /* _NEW_POINT */
253 key.lower_point_size = st->lower_point_size &&
254 !st_point_size_per_vertex(st->ctx);
255
256 /* _NEW_TRANSFORM */
257 if (st->lower_ucp && st_user_clip_planes_enabled(st->ctx))
258 key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled;
259 }
260
261 update_gl_clamp(st, st->ctx->VertexProgram._Current, key.gl_clamp);
262
263 simple_mtx_lock(&st->ctx->Shared->Mutex);
264 st->vp_variant = st_get_common_variant(st, stvp, &key);
265 simple_mtx_unlock(&st->ctx->Shared->Mutex);
266 }
267
268 st_reference_prog(st, &st->vp, stvp);
269
270 cso_set_vertex_shader_handle(st->cso_context,
271 st->vp_variant->base.driver_shader);
272 }
273
274
275 static void *
st_update_common_program(struct st_context * st,struct gl_program * prog,unsigned pipe_shader,struct st_program ** dst)276 st_update_common_program(struct st_context *st, struct gl_program *prog,
277 unsigned pipe_shader, struct st_program **dst)
278 {
279 struct st_program *stp;
280
281 if (!prog) {
282 st_reference_prog(st, dst, NULL);
283 return NULL;
284 }
285
286 stp = st_program(prog);
287 st_reference_prog(st, dst, stp);
288
289 if (st->shader_has_one_variant[prog->info.stage])
290 return stp->variants->driver_shader;
291
292 struct st_common_variant_key key;
293
294 /* use memset, not an initializer to be sure all memory is zeroed */
295 memset(&key, 0, sizeof(key));
296
297 key.st = st->has_shareable_shaders ? NULL : st;
298
299 if (pipe_shader == PIPE_SHADER_GEOMETRY ||
300 pipe_shader == PIPE_SHADER_TESS_EVAL) {
301 key.clamp_color = st->clamp_vert_color_in_shader &&
302 st->ctx->Light._ClampVertexColor &&
303 (stp->Base.info.outputs_written &
304 (VARYING_SLOT_COL0 |
305 VARYING_SLOT_COL1 |
306 VARYING_SLOT_BFC0 |
307 VARYING_SLOT_BFC1));
308
309 key.lower_depth_clamp =
310 (pipe_shader == PIPE_SHADER_GEOMETRY || !st->gp) &&
311 st->clamp_frag_depth_in_shader &&
312 (st->ctx->Transform.DepthClampNear ||
313 st->ctx->Transform.DepthClampFar);
314
315 if (key.lower_depth_clamp)
316 key.clip_negative_one_to_one =
317 st->ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE;
318
319 if (st->lower_ucp && st_user_clip_planes_enabled(st->ctx) &&
320 pipe_shader == PIPE_SHADER_GEOMETRY)
321 key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled;
322
323 key.lower_point_size = st->lower_point_size &&
324 !st_point_size_per_vertex(st->ctx);
325
326 }
327
328 update_gl_clamp(st, prog, key.gl_clamp);
329
330 simple_mtx_lock(&st->ctx->Shared->Mutex);
331 void *result = st_get_common_variant(st, stp, &key)->base.driver_shader;
332 simple_mtx_unlock(&st->ctx->Shared->Mutex);
333
334 return result;
335 }
336
337
338 void
st_update_gp(struct st_context * st)339 st_update_gp(struct st_context *st)
340 {
341 void *shader = st_update_common_program(st,
342 st->ctx->GeometryProgram._Current,
343 PIPE_SHADER_GEOMETRY, &st->gp);
344 cso_set_geometry_shader_handle(st->cso_context, shader);
345 }
346
347
348 void
st_update_tcp(struct st_context * st)349 st_update_tcp(struct st_context *st)
350 {
351 void *shader = st_update_common_program(st,
352 st->ctx->TessCtrlProgram._Current,
353 PIPE_SHADER_TESS_CTRL, &st->tcp);
354 cso_set_tessctrl_shader_handle(st->cso_context, shader);
355 }
356
357
358 void
st_update_tep(struct st_context * st)359 st_update_tep(struct st_context *st)
360 {
361 void *shader = st_update_common_program(st,
362 st->ctx->TessEvalProgram._Current,
363 PIPE_SHADER_TESS_EVAL, &st->tep);
364 cso_set_tesseval_shader_handle(st->cso_context, shader);
365 }
366
367
368 void
st_update_cp(struct st_context * st)369 st_update_cp(struct st_context *st)
370 {
371 void *shader = st_update_common_program(st,
372 st->ctx->ComputeProgram._Current,
373 PIPE_SHADER_COMPUTE, &st->cp);
374 cso_set_compute_shader_handle(st->cso_context, shader);
375 }
376