• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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