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#include "main/imports.h" 39#include "main/mtypes.h" 40#include "main/framebuffer.h" 41#include "main/texobj.h" 42#include "main/texstate.h" 43#include "program/program.h" 44 45#include "pipe/p_context.h" 46#include "pipe/p_shader_tokens.h" 47#include "util/u_simple_shaders.h" 48#include "cso_cache/cso_context.h" 49#include "util/u_debug.h" 50 51#include "st_context.h" 52#include "st_atom.h" 53#include "st_program.h" 54#include "st_texture.h" 55 56 57/** Compress the fog function enums into a 2-bit value */ 58static GLuint 59translate_fog_mode(GLenum mode) 60{ 61 switch (mode) { 62 case GL_LINEAR: return 1; 63 case GL_EXP: return 2; 64 case GL_EXP2: return 3; 65 default: 66 return 0; 67 } 68} 69 70static unsigned 71get_texture_target(struct gl_context *ctx, const unsigned unit) 72{ 73 struct gl_texture_object *texObj = _mesa_get_tex_unit(ctx, unit)->_Current; 74 gl_texture_index index; 75 76 if (texObj) { 77 index = _mesa_tex_target_to_index(ctx, texObj->Target); 78 } else { 79 /* fallback for missing texture */ 80 index = TEXTURE_2D_INDEX; 81 } 82 83 /* Map mesa texture target to TGSI texture target. 84 * Copied from st_mesa_to_tgsi.c, the shadow part is omitted */ 85 switch(index) { 86 case TEXTURE_2D_MULTISAMPLE_INDEX: return TGSI_TEXTURE_2D_MSAA; 87 case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY_MSAA; 88 case TEXTURE_BUFFER_INDEX: return TGSI_TEXTURE_BUFFER; 89 case TEXTURE_1D_INDEX: return TGSI_TEXTURE_1D; 90 case TEXTURE_2D_INDEX: return TGSI_TEXTURE_2D; 91 case TEXTURE_3D_INDEX: return TGSI_TEXTURE_3D; 92 case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE; 93 case TEXTURE_CUBE_ARRAY_INDEX: return TGSI_TEXTURE_CUBE_ARRAY; 94 case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT; 95 case TEXTURE_1D_ARRAY_INDEX: return TGSI_TEXTURE_1D_ARRAY; 96 case TEXTURE_2D_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY; 97 case TEXTURE_EXTERNAL_INDEX: return TGSI_TEXTURE_2D; 98 default: 99 debug_assert(0); 100 return TGSI_TEXTURE_1D; 101 } 102} 103 104 105/** 106 * Update fragment program state/atom. This involves translating the 107 * Mesa fragment program into a gallium fragment program and binding it. 108 */ 109static void 110update_fp( struct st_context *st ) 111{ 112 struct st_fragment_program *stfp; 113 struct st_fp_variant_key key; 114 115 assert(st->ctx->FragmentProgram._Current); 116 stfp = st_fragment_program(st->ctx->FragmentProgram._Current); 117 assert(stfp->Base.Target == GL_FRAGMENT_PROGRAM_ARB); 118 119 memset(&key, 0, sizeof(key)); 120 key.st = st->has_shareable_shaders ? NULL : st; 121 122 /* _NEW_FRAG_CLAMP */ 123 key.clamp_color = st->clamp_frag_color_in_shader && 124 st->ctx->Color._ClampFragmentColor; 125 126 /* _NEW_MULTISAMPLE | _NEW_BUFFERS */ 127 key.persample_shading = 128 st->force_persample_in_shader && 129 _mesa_is_multisample_enabled(st->ctx) && 130 st->ctx->Multisample.SampleShading && 131 st->ctx->Multisample.MinSampleShadingValue * 132 _mesa_geometric_samples(st->ctx->DrawBuffer) > 1; 133 134 if (stfp->ati_fs) { 135 unsigned u; 136 137 if (st->ctx->Fog.Enabled) { 138 key.fog = translate_fog_mode(st->ctx->Fog.Mode); 139 } 140 141 for (u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) { 142 key.texture_targets[u] = get_texture_target(st->ctx, u); 143 } 144 } 145 146 key.external = st_get_external_sampler_key(st, &stfp->Base); 147 148 st->fp_variant = st_get_fp_variant(st, stfp, &key); 149 150 st_reference_fragprog(st, &st->fp, stfp); 151 152 cso_set_fragment_shader_handle(st->cso_context, 153 st->fp_variant->driver_shader); 154} 155 156 157const struct st_tracked_state st_update_fp = { 158 update_fp /* update */ 159}; 160 161 162 163/** 164 * Update vertex program state/atom. This involves translating the 165 * Mesa vertex program into a gallium fragment program and binding it. 166 */ 167static void 168update_vp( struct st_context *st ) 169{ 170 struct st_vertex_program *stvp; 171 struct st_vp_variant_key key; 172 173 /* find active shader and params -- Should be covered by 174 * ST_NEW_VERTEX_PROGRAM 175 */ 176 assert(st->ctx->VertexProgram._Current); 177 stvp = st_vertex_program(st->ctx->VertexProgram._Current); 178 assert(stvp->Base.Target == GL_VERTEX_PROGRAM_ARB); 179 180 memset(&key, 0, sizeof key); 181 key.st = st->has_shareable_shaders ? NULL : st; 182 183 /* When this is true, we will add an extra input to the vertex 184 * shader translation (for edgeflags), an extra output with 185 * edgeflag semantics, and extend the vertex shader to pass through 186 * the input to the output. We'll need to use similar logic to set 187 * up the extra vertex_element input for edgeflags. 188 */ 189 key.passthrough_edgeflags = st->vertdata_edgeflags; 190 191 key.clamp_color = st->clamp_vert_color_in_shader && 192 st->ctx->Light._ClampVertexColor && 193 (stvp->Base.info.outputs_written & 194 (VARYING_SLOT_COL0 | 195 VARYING_SLOT_COL1 | 196 VARYING_SLOT_BFC0 | 197 VARYING_SLOT_BFC1)); 198 199 st->vp_variant = st_get_vp_variant(st, stvp, &key); 200 201 st_reference_vertprog(st, &st->vp, stvp); 202 203 cso_set_vertex_shader_handle(st->cso_context, 204 st->vp_variant->driver_shader); 205 206 st->vertex_result_to_slot = stvp->result_to_output; 207} 208 209 210const struct st_tracked_state st_update_vp = { 211 update_vp /* update */ 212}; 213 214 215 216static void 217update_gp( struct st_context *st ) 218{ 219 struct st_geometry_program *stgp; 220 221 if (!st->ctx->GeometryProgram._Current) { 222 cso_set_geometry_shader_handle(st->cso_context, NULL); 223 st_reference_geomprog(st, &st->gp, NULL); 224 return; 225 } 226 227 stgp = st_geometry_program(st->ctx->GeometryProgram._Current); 228 assert(stgp->Base.Target == GL_GEOMETRY_PROGRAM_NV); 229 230 st->gp_variant = st_get_basic_variant(st, PIPE_SHADER_GEOMETRY, 231 &stgp->tgsi, &stgp->variants); 232 233 st_reference_geomprog(st, &st->gp, stgp); 234 235 cso_set_geometry_shader_handle(st->cso_context, 236 st->gp_variant->driver_shader); 237} 238 239const struct st_tracked_state st_update_gp = { 240 update_gp /* update */ 241}; 242 243 244 245static void 246update_tcp( struct st_context *st ) 247{ 248 struct st_tessctrl_program *sttcp; 249 250 if (!st->ctx->TessCtrlProgram._Current) { 251 cso_set_tessctrl_shader_handle(st->cso_context, NULL); 252 st_reference_tesscprog(st, &st->tcp, NULL); 253 return; 254 } 255 256 sttcp = st_tessctrl_program(st->ctx->TessCtrlProgram._Current); 257 assert(sttcp->Base.Target == GL_TESS_CONTROL_PROGRAM_NV); 258 259 st->tcp_variant = st_get_basic_variant(st, PIPE_SHADER_TESS_CTRL, 260 &sttcp->tgsi, &sttcp->variants); 261 262 st_reference_tesscprog(st, &st->tcp, sttcp); 263 264 cso_set_tessctrl_shader_handle(st->cso_context, 265 st->tcp_variant->driver_shader); 266} 267 268const struct st_tracked_state st_update_tcp = { 269 update_tcp /* update */ 270}; 271 272 273 274static void 275update_tep( struct st_context *st ) 276{ 277 struct st_tesseval_program *sttep; 278 279 if (!st->ctx->TessEvalProgram._Current) { 280 cso_set_tesseval_shader_handle(st->cso_context, NULL); 281 st_reference_tesseprog(st, &st->tep, NULL); 282 return; 283 } 284 285 sttep = st_tesseval_program(st->ctx->TessEvalProgram._Current); 286 assert(sttep->Base.Target == GL_TESS_EVALUATION_PROGRAM_NV); 287 288 st->tep_variant = st_get_basic_variant(st, PIPE_SHADER_TESS_EVAL, 289 &sttep->tgsi, &sttep->variants); 290 291 st_reference_tesseprog(st, &st->tep, sttep); 292 293 cso_set_tesseval_shader_handle(st->cso_context, 294 st->tep_variant->driver_shader); 295} 296 297const struct st_tracked_state st_update_tep = { 298 update_tep /* update */ 299}; 300 301 302 303static void 304update_cp( struct st_context *st ) 305{ 306 struct st_compute_program *stcp; 307 308 if (!st->ctx->ComputeProgram._Current) { 309 cso_set_compute_shader_handle(st->cso_context, NULL); 310 st_reference_compprog(st, &st->cp, NULL); 311 return; 312 } 313 314 stcp = st_compute_program(st->ctx->ComputeProgram._Current); 315 assert(stcp->Base.Target == GL_COMPUTE_PROGRAM_NV); 316 317 st->cp_variant = st_get_cp_variant(st, &stcp->tgsi, &stcp->variants); 318 319 st_reference_compprog(st, &st->cp, stcp); 320 321 cso_set_compute_shader_handle(st->cso_context, 322 st->cp_variant->driver_shader); 323} 324 325const struct st_tracked_state st_update_cp = { 326 update_cp /* update */ 327}; 328