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 * Authors: 30 * Keith Whitwell <keithw (at) vmware.com> 31 */ 32 33 #include "main/glheader.h" 34 #include "main/macros.h" 35 #include "main/enums.h" 36 #include "main/shaderapi.h" 37 #include "program/prog_instruction.h" 38 #include "program/program.h" 39 40 #include "cso_cache/cso_context.h" 41 #include "draw/draw_context.h" 42 43 #include "st_context.h" 44 #include "st_debug.h" 45 #include "st_program.h" 46 #include "st_mesa_to_tgsi.h" 47 #include "st_cb_program.h" 48 #include "st_glsl_to_tgsi.h" 49 #include "st_atifs_to_tgsi.h" 50 51 52 /** 53 * Called via ctx->Driver.NewProgram() to allocate a new vertex or 54 * fragment program. 55 */ 56 static struct gl_program * 57 st_new_program(struct gl_context *ctx, GLenum target, GLuint id, 58 bool is_arb_asm) 59 { 60 switch (target) { 61 case GL_VERTEX_PROGRAM_ARB: { 62 struct st_vertex_program *prog = rzalloc(NULL, 63 struct st_vertex_program); 64 return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm); 65 } 66 case GL_FRAGMENT_PROGRAM_ARB: { 67 struct st_fragment_program *prog = rzalloc(NULL, 68 struct st_fragment_program); 69 return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm); 70 } 71 case GL_TESS_CONTROL_PROGRAM_NV: 72 case GL_TESS_EVALUATION_PROGRAM_NV: 73 case GL_GEOMETRY_PROGRAM_NV: { 74 struct st_common_program *prog = rzalloc(NULL, 75 struct st_common_program); 76 return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm); 77 } 78 case GL_COMPUTE_PROGRAM_NV: { 79 struct st_compute_program *prog = rzalloc(NULL, 80 struct st_compute_program); 81 return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm); 82 } 83 default: 84 assert(0); 85 return NULL; 86 } 87 } 88 89 90 /** 91 * Called via ctx->Driver.DeleteProgram() 92 */ 93 static void 94 st_delete_program(struct gl_context *ctx, struct gl_program *prog) 95 { 96 struct st_context *st = st_context(ctx); 97 98 switch( prog->Target ) { 99 case GL_VERTEX_PROGRAM_ARB: 100 { 101 struct st_vertex_program *stvp = (struct st_vertex_program *) prog; 102 st_release_vp_variants( st, stvp ); 103 104 if (stvp->glsl_to_tgsi) 105 free_glsl_to_tgsi_visitor(stvp->glsl_to_tgsi); 106 } 107 break; 108 case GL_TESS_CONTROL_PROGRAM_NV: 109 case GL_TESS_EVALUATION_PROGRAM_NV: 110 case GL_GEOMETRY_PROGRAM_NV: 111 { 112 struct st_common_program *p = st_common_program(prog); 113 114 st_release_basic_variants(st, p->Base.Target, &p->variants, 115 &p->tgsi); 116 117 if (p->glsl_to_tgsi) 118 free_glsl_to_tgsi_visitor(p->glsl_to_tgsi); 119 } 120 break; 121 case GL_FRAGMENT_PROGRAM_ARB: 122 { 123 struct st_fragment_program *stfp = 124 (struct st_fragment_program *) prog; 125 126 st_release_fp_variants(st, stfp); 127 128 if (stfp->glsl_to_tgsi) 129 free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi); 130 } 131 break; 132 case GL_COMPUTE_PROGRAM_NV: 133 { 134 struct st_compute_program *stcp = 135 (struct st_compute_program *) prog; 136 137 st_release_cp_variants(st, stcp); 138 139 if (stcp->glsl_to_tgsi) 140 free_glsl_to_tgsi_visitor(stcp->glsl_to_tgsi); 141 } 142 break; 143 default: 144 assert(0); /* problem */ 145 } 146 147 /* delete base class */ 148 _mesa_delete_program( ctx, prog ); 149 } 150 151 152 /** 153 * Called via ctx->Driver.ProgramStringNotify() 154 * Called when the program's text/code is changed. We have to free 155 * all shader variants and corresponding gallium shaders when this happens. 156 */ 157 static GLboolean 158 st_program_string_notify( struct gl_context *ctx, 159 GLenum target, 160 struct gl_program *prog ) 161 { 162 struct st_context *st = st_context(ctx); 163 gl_shader_stage stage = _mesa_program_enum_to_shader_stage(target); 164 165 if (target == GL_FRAGMENT_PROGRAM_ARB) { 166 struct st_fragment_program *stfp = (struct st_fragment_program *) prog; 167 168 st_release_fp_variants(st, stfp); 169 if (!st_translate_fragment_program(st, stfp)) 170 return false; 171 172 if (st->fp == stfp) 173 st->dirty |= stfp->affected_states; 174 } 175 else if (target == GL_GEOMETRY_PROGRAM_NV) { 176 struct st_common_program *stgp = st_common_program(prog); 177 178 st_release_basic_variants(st, stgp->Base.Target, &stgp->variants, 179 &stgp->tgsi); 180 if (!st_translate_geometry_program(st, stgp)) 181 return false; 182 183 if (st->gp == stgp) 184 st->dirty |= stgp->affected_states; 185 } 186 else if (target == GL_VERTEX_PROGRAM_ARB) { 187 struct st_vertex_program *stvp = (struct st_vertex_program *) prog; 188 189 st_release_vp_variants(st, stvp); 190 if (!st_translate_vertex_program(st, stvp)) 191 return false; 192 193 if (st->vp == stvp) 194 st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp); 195 } 196 else if (target == GL_TESS_CONTROL_PROGRAM_NV) { 197 struct st_common_program *sttcp = 198 st_common_program(prog); 199 200 st_release_basic_variants(st, sttcp->Base.Target, &sttcp->variants, 201 &sttcp->tgsi); 202 if (!st_translate_tessctrl_program(st, sttcp)) 203 return false; 204 205 if (st->tcp == sttcp) 206 st->dirty |= sttcp->affected_states; 207 } 208 else if (target == GL_TESS_EVALUATION_PROGRAM_NV) { 209 struct st_common_program *sttep = 210 st_common_program(prog); 211 212 st_release_basic_variants(st, sttep->Base.Target, &sttep->variants, 213 &sttep->tgsi); 214 if (!st_translate_tesseval_program(st, sttep)) 215 return false; 216 217 if (st->tep == sttep) 218 st->dirty |= sttep->affected_states; 219 } 220 else if (target == GL_COMPUTE_PROGRAM_NV) { 221 struct st_compute_program *stcp = 222 (struct st_compute_program *) prog; 223 224 st_release_cp_variants(st, stcp); 225 if (!st_translate_compute_program(st, stcp)) 226 return false; 227 228 if (st->cp == stcp) 229 st->dirty |= stcp->affected_states; 230 } 231 else if (target == GL_FRAGMENT_SHADER_ATI) { 232 assert(prog); 233 234 struct st_fragment_program *stfp = (struct st_fragment_program *) prog; 235 assert(stfp->ati_fs); 236 assert(stfp->ati_fs->Program == prog); 237 238 st_init_atifs_prog(ctx, prog); 239 240 st_release_fp_variants(st, stfp); 241 if (!st_translate_fragment_program(st, stfp)) 242 return false; 243 244 if (st->fp == stfp) 245 st->dirty |= stfp->affected_states; 246 } 247 248 if (ST_DEBUG & DEBUG_PRECOMPILE || 249 st->shader_has_one_variant[stage]) 250 st_precompile_shader_variant(st, prog); 251 252 return GL_TRUE; 253 } 254 255 /** 256 * Called via ctx->Driver.NewATIfs() 257 * Called in glEndFragmentShaderATI() 258 */ 259 static struct gl_program * 260 st_new_ati_fs(struct gl_context *ctx, struct ati_fragment_shader *curProg) 261 { 262 struct gl_program *prog = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 263 curProg->Id, true); 264 struct st_fragment_program *stfp = (struct st_fragment_program *)prog; 265 stfp->ati_fs = curProg; 266 return prog; 267 } 268 269 /** 270 * Plug in the program and shader-related device driver functions. 271 */ 272 void 273 st_init_program_functions(struct dd_function_table *functions) 274 { 275 functions->NewProgram = st_new_program; 276 functions->DeleteProgram = st_delete_program; 277 functions->ProgramStringNotify = st_program_string_notify; 278 functions->NewATIfs = st_new_ati_fs; 279 280 functions->LinkShader = st_link_shader; 281 } 282