• 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_target(struct gl_context * ctx,const unsigned unit)60 get_texture_target(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    /* Map mesa texture target to TGSI texture target.
73     * Copied from st_mesa_to_tgsi.c, the shadow part is omitted */
74    switch(index) {
75    case TEXTURE_2D_MULTISAMPLE_INDEX: return TGSI_TEXTURE_2D_MSAA;
76    case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY_MSAA;
77    case TEXTURE_BUFFER_INDEX: return TGSI_TEXTURE_BUFFER;
78    case TEXTURE_1D_INDEX:   return TGSI_TEXTURE_1D;
79    case TEXTURE_2D_INDEX:   return TGSI_TEXTURE_2D;
80    case TEXTURE_3D_INDEX:   return TGSI_TEXTURE_3D;
81    case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE;
82    case TEXTURE_CUBE_ARRAY_INDEX: return TGSI_TEXTURE_CUBE_ARRAY;
83    case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT;
84    case TEXTURE_1D_ARRAY_INDEX:   return TGSI_TEXTURE_1D_ARRAY;
85    case TEXTURE_2D_ARRAY_INDEX:   return TGSI_TEXTURE_2D_ARRAY;
86    case TEXTURE_EXTERNAL_INDEX:   return TGSI_TEXTURE_2D;
87    default:
88       debug_assert(0);
89       return TGSI_TEXTURE_1D;
90    }
91 }
92 
93 
94 /**
95  * Update fragment program state/atom.  This involves translating the
96  * Mesa fragment program into a gallium fragment program and binding it.
97  */
98 void
st_update_fp(struct st_context * st)99 st_update_fp( struct st_context *st )
100 {
101    struct st_program *stfp;
102 
103    assert(st->ctx->FragmentProgram._Current);
104    stfp = st_program(st->ctx->FragmentProgram._Current);
105    assert(stfp->Base.Target == GL_FRAGMENT_PROGRAM_ARB);
106 
107    void *shader;
108 
109    if (st->shader_has_one_variant[MESA_SHADER_FRAGMENT] &&
110        !stfp->ati_fs && /* ATI_fragment_shader always has multiple variants */
111        !stfp->Base.ExternalSamplersUsed && /* external samplers need variants */
112        stfp->variants &&
113        !st_fp_variant(stfp->variants)->key.drawpixels &&
114        !st_fp_variant(stfp->variants)->key.bitmap) {
115       shader = stfp->variants->driver_shader;
116    } else {
117       struct st_fp_variant_key key;
118 
119       /* use memset, not an initializer to be sure all memory is zeroed */
120       memset(&key, 0, sizeof(key));
121 
122       key.st = st->has_shareable_shaders ? NULL : st;
123 
124       key.lower_flatshade = st->lower_flatshade &&
125                             st->ctx->Light.ShadeModel == GL_FLAT;
126 
127       /* _NEW_COLOR */
128       key.lower_alpha_func = COMPARE_FUNC_ALWAYS;
129       if (st->lower_alpha_test && _mesa_is_alpha_test_enabled(st->ctx))
130          key.lower_alpha_func = st->ctx->Color.AlphaFunc;
131 
132       /* _NEW_LIGHT | _NEW_PROGRAM */
133       key.lower_two_sided_color = st->lower_two_sided_color &&
134          _mesa_vertex_program_two_side_enabled(st->ctx);
135 
136       /* gl_driver_flags::NewFragClamp */
137       key.clamp_color = st->clamp_frag_color_in_shader &&
138                         st->ctx->Color._ClampFragmentColor;
139 
140       /* _NEW_MULTISAMPLE | _NEW_BUFFERS */
141       key.persample_shading =
142          st->force_persample_in_shader &&
143          _mesa_is_multisample_enabled(st->ctx) &&
144          st->ctx->Multisample.SampleShading &&
145          st->ctx->Multisample.MinSampleShadingValue *
146          _mesa_geometric_samples(st->ctx->DrawBuffer) > 1;
147 
148       key.lower_depth_clamp =
149          st->clamp_frag_depth_in_shader &&
150          (st->ctx->Transform.DepthClampNear ||
151           st->ctx->Transform.DepthClampFar);
152 
153       if (stfp->ati_fs) {
154          key.fog = st->ctx->Fog._PackedEnabledMode;
155 
156          for (unsigned u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) {
157             key.texture_targets[u] = get_texture_target(st->ctx, u);
158          }
159       }
160 
161       key.external = st_get_external_sampler_key(st, &stfp->Base);
162 
163       simple_mtx_lock(&st->ctx->Shared->Mutex);
164       shader = st_get_fp_variant(st, stfp, &key)->base.driver_shader;
165       simple_mtx_unlock(&st->ctx->Shared->Mutex);
166    }
167 
168    st_reference_prog(st, &st->fp, stfp);
169 
170    cso_set_fragment_shader_handle(st->cso_context, shader);
171 }
172 
173 
174 /**
175  * Update vertex program state/atom.  This involves translating the
176  * Mesa vertex program into a gallium fragment program and binding it.
177  */
178 void
st_update_vp(struct st_context * st)179 st_update_vp( struct st_context *st )
180 {
181    struct st_program *stvp;
182 
183    /* find active shader and params -- Should be covered by
184     * ST_NEW_VERTEX_PROGRAM
185     */
186    assert(st->ctx->VertexProgram._Current);
187    stvp = st_program(st->ctx->VertexProgram._Current);
188    assert(stvp->Base.Target == GL_VERTEX_PROGRAM_ARB);
189 
190    if (st->shader_has_one_variant[MESA_SHADER_VERTEX] &&
191        stvp->variants &&
192        st_common_variant(stvp->variants)->key.passthrough_edgeflags == st->vertdata_edgeflags &&
193        !st_common_variant(stvp->variants)->key.is_draw_shader) {
194       st->vp_variant = st_common_variant(stvp->variants);
195    } else {
196       struct st_common_variant_key key;
197 
198       memset(&key, 0, sizeof(key));
199 
200       key.st = st->has_shareable_shaders ? NULL : st;
201 
202       /* When this is true, we will add an extra input to the vertex
203        * shader translation (for edgeflags), an extra output with
204        * edgeflag semantics, and extend the vertex shader to pass through
205        * the input to the output.  We'll need to use similar logic to set
206        * up the extra vertex_element input for edgeflags.
207        */
208       key.passthrough_edgeflags = st->vertdata_edgeflags;
209 
210       key.clamp_color = st->clamp_vert_color_in_shader &&
211                         st->ctx->Light._ClampVertexColor &&
212                         (stvp->Base.info.outputs_written &
213                          (VARYING_SLOT_COL0 |
214                           VARYING_SLOT_COL1 |
215                           VARYING_SLOT_BFC0 |
216                           VARYING_SLOT_BFC1));
217 
218       key.lower_depth_clamp =
219             !st->gp && !st->tep &&
220             st->clamp_frag_depth_in_shader &&
221             (st->ctx->Transform.DepthClampNear ||
222              st->ctx->Transform.DepthClampFar);
223 
224       if (key.lower_depth_clamp)
225          key.clip_negative_one_to_one =
226                st->ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE;
227 
228       /* _NEW_POINT */
229       key.lower_point_size = st->lower_point_size &&
230                              !st_point_size_per_vertex(st->ctx);
231 
232       /* _NEW_TRANSFORM */
233       if (st->lower_ucp && st_user_clip_planes_enabled(st->ctx) &&
234           !st->ctx->GeometryProgram._Current)
235          key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled;
236 
237       simple_mtx_lock(&st->ctx->Shared->Mutex);
238       st->vp_variant = st_get_vp_variant(st, stvp, &key);
239       simple_mtx_unlock(&st->ctx->Shared->Mutex);
240    }
241 
242    st_reference_prog(st, &st->vp, stvp);
243 
244    cso_set_vertex_shader_handle(st->cso_context,
245                                 st->vp_variant->base.driver_shader);
246 }
247 
248 
249 static void *
st_update_common_program(struct st_context * st,struct gl_program * prog,unsigned pipe_shader,struct st_program ** dst)250 st_update_common_program(struct st_context *st, struct gl_program *prog,
251                          unsigned pipe_shader, struct st_program **dst)
252 {
253    struct st_program *stp;
254 
255    if (!prog) {
256       st_reference_prog(st, dst, NULL);
257       return NULL;
258    }
259 
260    stp = st_program(prog);
261    st_reference_prog(st, dst, stp);
262 
263    if (st->shader_has_one_variant[prog->info.stage] && stp->variants)
264       return stp->variants->driver_shader;
265 
266    struct st_common_variant_key key;
267 
268    /* use memset, not an initializer to be sure all memory is zeroed */
269    memset(&key, 0, sizeof(key));
270 
271    key.st = st->has_shareable_shaders ? NULL : st;
272 
273    if (pipe_shader == PIPE_SHADER_GEOMETRY ||
274        pipe_shader == PIPE_SHADER_TESS_EVAL) {
275       key.clamp_color = st->clamp_vert_color_in_shader &&
276                         st->ctx->Light._ClampVertexColor &&
277                         (stp->Base.info.outputs_written &
278                          (VARYING_SLOT_COL0 |
279                           VARYING_SLOT_COL1 |
280                           VARYING_SLOT_BFC0 |
281                           VARYING_SLOT_BFC1));
282 
283       key.lower_depth_clamp =
284             (pipe_shader == PIPE_SHADER_GEOMETRY || !st->gp) &&
285             st->clamp_frag_depth_in_shader &&
286             (st->ctx->Transform.DepthClampNear ||
287              st->ctx->Transform.DepthClampFar);
288 
289       if (key.lower_depth_clamp)
290          key.clip_negative_one_to_one =
291                st->ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE;
292 
293       if (st->lower_ucp && st_user_clip_planes_enabled(st->ctx) &&
294           pipe_shader == PIPE_SHADER_GEOMETRY)
295          key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled;
296    }
297 
298    simple_mtx_lock(&st->ctx->Shared->Mutex);
299    void *result = st_get_common_variant(st, stp, &key)->driver_shader;
300    simple_mtx_unlock(&st->ctx->Shared->Mutex);
301 
302    return result;
303 }
304 
305 
306 void
st_update_gp(struct st_context * st)307 st_update_gp(struct st_context *st)
308 {
309    void *shader = st_update_common_program(st,
310                                            st->ctx->GeometryProgram._Current,
311                                            PIPE_SHADER_GEOMETRY, &st->gp);
312    cso_set_geometry_shader_handle(st->cso_context, shader);
313 }
314 
315 
316 void
st_update_tcp(struct st_context * st)317 st_update_tcp(struct st_context *st)
318 {
319    void *shader = st_update_common_program(st,
320                                            st->ctx->TessCtrlProgram._Current,
321                                            PIPE_SHADER_TESS_CTRL, &st->tcp);
322    cso_set_tessctrl_shader_handle(st->cso_context, shader);
323 }
324 
325 
326 void
st_update_tep(struct st_context * st)327 st_update_tep(struct st_context *st)
328 {
329    void *shader = st_update_common_program(st,
330                                            st->ctx->TessEvalProgram._Current,
331                                            PIPE_SHADER_TESS_EVAL, &st->tep);
332    cso_set_tesseval_shader_handle(st->cso_context, shader);
333 }
334 
335 
336 void
st_update_cp(struct st_context * st)337 st_update_cp(struct st_context *st)
338 {
339    void *shader = st_update_common_program(st,
340                                            st->ctx->ComputeProgram._Current,
341                                            PIPE_SHADER_COMPUTE, &st->cp);
342    cso_set_compute_shader_handle(st->cso_context, shader);
343 }
344