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 59static unsigned 60get_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 75static void 76update_gl_clamp(struct st_context *st, struct gl_program *prog, uint32_t *gl_clamp) 77{ 78 if (!st->emulate_gl_clamp) 79 return; 80 81 gl_clamp[0] = gl_clamp[1] = gl_clamp[2] = 0; 82 GLbitfield samplers_used = prog->SamplersUsed; 83 unsigned unit; 84 /* same as st_atom_sampler.c */ 85 for (unit = 0; samplers_used; unit++, samplers_used >>= 1) { 86 unsigned tex_unit = prog->SamplerUnits[unit]; 87 if (samplers_used & 1 && 88 (st->ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER || 89 st->texture_buffer_sampler)) { 90 const struct gl_texture_object *texobj; 91 struct gl_context *ctx = st->ctx; 92 const struct gl_sampler_object *msamp; 93 94 texobj = ctx->Texture.Unit[tex_unit]._Current; 95 assert(texobj); 96 97 msamp = _mesa_get_samplerobj(ctx, tex_unit); 98 if (is_wrap_gl_clamp(msamp->Attrib.WrapS)) 99 gl_clamp[0] |= BITFIELD64_BIT(unit); 100 if (is_wrap_gl_clamp(msamp->Attrib.WrapT)) 101 gl_clamp[1] |= BITFIELD64_BIT(unit); 102 if (is_wrap_gl_clamp(msamp->Attrib.WrapR)) 103 gl_clamp[2] |= BITFIELD64_BIT(unit); 104 } 105 } 106} 107 108/** 109 * Update fragment program state/atom. This involves translating the 110 * Mesa fragment program into a gallium fragment program and binding it. 111 */ 112void 113st_update_fp( struct st_context *st ) 114{ 115 struct gl_program *fp; 116 117 assert(st->ctx->FragmentProgram._Current); 118 fp = st->ctx->FragmentProgram._Current; 119 assert(fp->Target == GL_FRAGMENT_PROGRAM_ARB); 120 121 void *shader; 122 123 if (st->shader_has_one_variant[MESA_SHADER_FRAGMENT] && 124 !fp->ati_fs && /* ATI_fragment_shader always has multiple variants */ 125 !fp->ExternalSamplersUsed /* external samplers need variants */) { 126 shader = fp->variants->driver_shader; 127 } else { 128 struct st_fp_variant_key key; 129 130 /* use memset, not an initializer to be sure all memory is zeroed */ 131 memset(&key, 0, sizeof(key)); 132 133 key.st = st->has_shareable_shaders ? NULL : st; 134 135 key.lower_flatshade = st->lower_flatshade && 136 st->ctx->Light.ShadeModel == GL_FLAT; 137 138 /* _NEW_COLOR */ 139 key.lower_alpha_func = COMPARE_FUNC_ALWAYS; 140 if (st->lower_alpha_test && _mesa_is_alpha_test_enabled(st->ctx)) 141 key.lower_alpha_func = st->ctx->Color.AlphaFunc; 142 143 /* _NEW_LIGHT_STATE | _NEW_PROGRAM */ 144 key.lower_two_sided_color = st->lower_two_sided_color && 145 _mesa_vertex_program_two_side_enabled(st->ctx); 146 147 /* _NEW_POINT | _NEW_PROGRAM */ 148 if (st->lower_texcoord_replace && st->ctx->Point.PointSprite && 149 st->ctx->Point.CoordReplace) 150 key.lower_texcoord_replace = st->ctx->Point.CoordReplace; 151 152 /* gl_driver_flags::NewFragClamp */ 153 key.clamp_color = st->clamp_frag_color_in_shader && 154 st->ctx->Color._ClampFragmentColor; 155 156 /* _NEW_MULTISAMPLE | _NEW_BUFFERS */ 157 key.persample_shading = 158 st->force_persample_in_shader && 159 _mesa_is_multisample_enabled(st->ctx) && 160 st->ctx->Multisample.SampleShading && 161 st->ctx->Multisample.MinSampleShadingValue * 162 _mesa_geometric_samples(st->ctx->DrawBuffer) > 1; 163 164 if (fp->ati_fs) { 165 key.fog = st->ctx->Fog._PackedEnabledMode; 166 167 for (unsigned u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) { 168 key.texture_index[u] = get_texture_index(st->ctx, u); 169 } 170 } 171 172 key.external = st_get_external_sampler_key(st, fp); 173 update_gl_clamp(st, st->ctx->FragmentProgram._Current, key.gl_clamp); 174 175 simple_mtx_lock(&st->ctx->Shared->Mutex); 176 shader = st_get_fp_variant(st, fp, &key)->base.driver_shader; 177 simple_mtx_unlock(&st->ctx->Shared->Mutex); 178 } 179 180 _mesa_reference_program(st->ctx, &st->fp, fp); 181 182 cso_set_fragment_shader_handle(st->cso_context, shader); 183} 184 185 186/** 187 * Update vertex program state/atom. This involves translating the 188 * Mesa vertex program into a gallium fragment program and binding it. 189 */ 190void 191st_update_vp( struct st_context *st ) 192{ 193 struct gl_program *vp; 194 195 /* find active shader and params -- Should be covered by 196 * ST_NEW_VERTEX_PROGRAM 197 */ 198 assert(st->ctx->VertexProgram._Current); 199 vp = st->ctx->VertexProgram._Current; 200 assert(vp->Target == GL_VERTEX_PROGRAM_ARB); 201 202 if (st->shader_has_one_variant[MESA_SHADER_VERTEX] && 203 !st->vertdata_edgeflags) { 204 st->vp_variant = st_common_variant(vp->variants); 205 } else { 206 struct st_common_variant_key key; 207 208 memset(&key, 0, sizeof(key)); 209 210 key.st = st->has_shareable_shaders ? NULL : st; 211 212 /* When this is true, we will add an extra input to the vertex 213 * shader translation (for edgeflags), an extra output with 214 * edgeflag semantics, and extend the vertex shader to pass through 215 * the input to the output. We'll need to use similar logic to set 216 * up the extra vertex_element input for edgeflags. 217 */ 218 key.passthrough_edgeflags = st->vertdata_edgeflags; 219 220 key.clamp_color = st->clamp_vert_color_in_shader && 221 st->ctx->Light._ClampVertexColor && 222 (vp->info.outputs_written & 223 (VARYING_SLOT_COL0 | 224 VARYING_SLOT_COL1 | 225 VARYING_SLOT_BFC0 | 226 VARYING_SLOT_BFC1)); 227 228 if (!st->ctx->GeometryProgram._Current && 229 !st->ctx->TessEvalProgram._Current) { 230 /* _NEW_POINT */ 231 if (st->lower_point_size) 232 key.export_point_size = !st->ctx->VertexProgram.PointSizeEnabled && !st->ctx->PointSizeIsSet; 233 /* _NEW_TRANSFORM */ 234 if (st->lower_ucp && st_user_clip_planes_enabled(st->ctx)) 235 key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled; 236 } 237 238 update_gl_clamp(st, st->ctx->VertexProgram._Current, key.gl_clamp); 239 240 simple_mtx_lock(&st->ctx->Shared->Mutex); 241 st->vp_variant = st_get_common_variant(st, vp, &key); 242 simple_mtx_unlock(&st->ctx->Shared->Mutex); 243 } 244 245 _mesa_reference_program(st->ctx, &st->vp, vp); 246 247 cso_set_vertex_shader_handle(st->cso_context, 248 st->vp_variant->base.driver_shader); 249} 250 251 252static void * 253st_update_common_program(struct st_context *st, struct gl_program *prog, 254 unsigned pipe_shader, struct gl_program **dst) 255{ 256 if (!prog) { 257 _mesa_reference_program(st->ctx, dst, NULL); 258 return NULL; 259 } 260 261 _mesa_reference_program(st->ctx, dst, prog); 262 263 if (st->shader_has_one_variant[prog->info.stage]) 264 return prog->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 (prog->info.outputs_written & 278 (VARYING_SLOT_COL0 | 279 VARYING_SLOT_COL1 | 280 VARYING_SLOT_BFC0 | 281 VARYING_SLOT_BFC1)); 282 283 if (st->lower_ucp && st_user_clip_planes_enabled(st->ctx) && 284 (pipe_shader == PIPE_SHADER_GEOMETRY || 285 !st->ctx->GeometryProgram._Current)) 286 key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled; 287 288 if (st->lower_point_size) 289 key.export_point_size = !st->ctx->VertexProgram.PointSizeEnabled && !st->ctx->PointSizeIsSet; 290 } 291 292 update_gl_clamp(st, prog, key.gl_clamp); 293 294 simple_mtx_lock(&st->ctx->Shared->Mutex); 295 void *result = st_get_common_variant(st, prog, &key)->base.driver_shader; 296 simple_mtx_unlock(&st->ctx->Shared->Mutex); 297 298 return result; 299} 300 301 302void 303st_update_gp(struct st_context *st) 304{ 305 void *shader = st_update_common_program(st, 306 st->ctx->GeometryProgram._Current, 307 PIPE_SHADER_GEOMETRY, &st->gp); 308 cso_set_geometry_shader_handle(st->cso_context, shader); 309} 310 311 312void 313st_update_tcp(struct st_context *st) 314{ 315 void *shader = st_update_common_program(st, 316 st->ctx->TessCtrlProgram._Current, 317 PIPE_SHADER_TESS_CTRL, &st->tcp); 318 cso_set_tessctrl_shader_handle(st->cso_context, shader); 319} 320 321 322void 323st_update_tep(struct st_context *st) 324{ 325 void *shader = st_update_common_program(st, 326 st->ctx->TessEvalProgram._Current, 327 PIPE_SHADER_TESS_EVAL, &st->tep); 328 cso_set_tesseval_shader_handle(st->cso_context, shader); 329} 330 331 332void 333st_update_cp(struct st_context *st) 334{ 335 void *shader = st_update_common_program(st, 336 st->ctx->ComputeProgram._Current, 337 PIPE_SHADER_COMPUTE, &st->cp); 338 cso_set_compute_shader_handle(st->cso_context, shader); 339} 340