1 /************************************************************************** 2 * 3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 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 TUNGSTEN GRAPHICS 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 <keith (at) tungstengraphics.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_program.h" 45 #include "st_mesa_to_tgsi.h" 46 #include "st_cb_program.h" 47 #include "st_glsl_to_tgsi.h" 48 49 50 51 /** 52 * Called via ctx->Driver.BindProgram() to bind an ARB vertex or 53 * fragment program. 54 */ 55 static void 56 st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog) 57 { 58 struct st_context *st = st_context(ctx); 59 60 switch (target) { 61 case GL_VERTEX_PROGRAM_ARB: 62 st->dirty.st |= ST_NEW_VERTEX_PROGRAM; 63 break; 64 case GL_FRAGMENT_PROGRAM_ARB: 65 st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; 66 break; 67 case MESA_GEOMETRY_PROGRAM: 68 st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM; 69 break; 70 } 71 } 72 73 74 /** 75 * Called via ctx->Driver.UseProgram() to bind a linked GLSL program 76 * (vertex shader + fragment shader). 77 */ 78 static void 79 st_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) 80 { 81 struct st_context *st = st_context(ctx); 82 83 st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; 84 st->dirty.st |= ST_NEW_VERTEX_PROGRAM; 85 st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM; 86 } 87 88 89 /** 90 * Called via ctx->Driver.NewProgram() to allocate a new vertex or 91 * fragment program. 92 */ 93 static struct gl_program * 94 st_new_program(struct gl_context *ctx, GLenum target, GLuint id) 95 { 96 switch (target) { 97 case GL_VERTEX_PROGRAM_ARB: { 98 struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program); 99 return _mesa_init_vertex_program(ctx, &prog->Base, target, id); 100 } 101 102 case GL_FRAGMENT_PROGRAM_ARB: 103 case GL_FRAGMENT_PROGRAM_NV: { 104 struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program); 105 return _mesa_init_fragment_program(ctx, &prog->Base, target, id); 106 } 107 108 case MESA_GEOMETRY_PROGRAM: { 109 struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program); 110 return _mesa_init_geometry_program(ctx, &prog->Base, target, id); 111 } 112 113 default: 114 assert(0); 115 return NULL; 116 } 117 } 118 119 120 /** 121 * Called via ctx->Driver.DeleteProgram() 122 */ 123 static void 124 st_delete_program(struct gl_context *ctx, struct gl_program *prog) 125 { 126 struct st_context *st = st_context(ctx); 127 128 switch( prog->Target ) { 129 case GL_VERTEX_PROGRAM_ARB: 130 { 131 struct st_vertex_program *stvp = (struct st_vertex_program *) prog; 132 st_release_vp_variants( st, stvp ); 133 134 if (stvp->glsl_to_tgsi) 135 free_glsl_to_tgsi_visitor(stvp->glsl_to_tgsi); 136 } 137 break; 138 case MESA_GEOMETRY_PROGRAM: 139 { 140 struct st_geometry_program *stgp = 141 (struct st_geometry_program *) prog; 142 143 st_release_gp_variants(st, stgp); 144 145 if (stgp->glsl_to_tgsi) 146 free_glsl_to_tgsi_visitor(stgp->glsl_to_tgsi); 147 148 if (stgp->tgsi.tokens) { 149 st_free_tokens((void *) stgp->tgsi.tokens); 150 stgp->tgsi.tokens = NULL; 151 } 152 } 153 break; 154 case GL_FRAGMENT_PROGRAM_ARB: 155 { 156 struct st_fragment_program *stfp = 157 (struct st_fragment_program *) prog; 158 159 st_release_fp_variants(st, stfp); 160 161 if (stfp->glsl_to_tgsi) 162 free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi); 163 } 164 break; 165 default: 166 assert(0); /* problem */ 167 } 168 169 /* delete base class */ 170 _mesa_delete_program( ctx, prog ); 171 } 172 173 174 /** 175 * Called via ctx->Driver.IsProgramNative() 176 */ 177 static GLboolean 178 st_is_program_native(struct gl_context *ctx, 179 GLenum target, 180 struct gl_program *prog) 181 { 182 return GL_TRUE; 183 } 184 185 186 /** 187 * Called via ctx->Driver.ProgramStringNotify() 188 * Called when the program's text/code is changed. We have to free 189 * all shader variants and corresponding gallium shaders when this happens. 190 */ 191 static GLboolean 192 st_program_string_notify( struct gl_context *ctx, 193 GLenum target, 194 struct gl_program *prog ) 195 { 196 struct st_context *st = st_context(ctx); 197 198 if (target == GL_FRAGMENT_PROGRAM_ARB) { 199 struct st_fragment_program *stfp = (struct st_fragment_program *) prog; 200 201 st_release_fp_variants(st, stfp); 202 203 if (st->fp == stfp) 204 st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; 205 } 206 else if (target == MESA_GEOMETRY_PROGRAM) { 207 struct st_geometry_program *stgp = (struct st_geometry_program *) prog; 208 209 st_release_gp_variants(st, stgp); 210 211 if (stgp->tgsi.tokens) { 212 st_free_tokens((void *) stgp->tgsi.tokens); 213 stgp->tgsi.tokens = NULL; 214 } 215 216 if (st->gp == stgp) 217 st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM; 218 } 219 else if (target == GL_VERTEX_PROGRAM_ARB) { 220 struct st_vertex_program *stvp = (struct st_vertex_program *) prog; 221 222 st_release_vp_variants( st, stvp ); 223 224 if (st->vp == stvp) 225 st->dirty.st |= ST_NEW_VERTEX_PROGRAM; 226 } 227 228 /* XXX check if program is legal, within limits */ 229 return GL_TRUE; 230 } 231 232 233 /** 234 * Plug in the program and shader-related device driver functions. 235 */ 236 void 237 st_init_program_functions(struct dd_function_table *functions) 238 { 239 functions->BindProgram = st_bind_program; 240 functions->UseProgram = st_use_program; 241 functions->NewProgram = st_new_program; 242 functions->DeleteProgram = st_delete_program; 243 functions->IsProgramNative = st_is_program_native; 244 functions->ProgramStringNotify = st_program_string_notify; 245 246 functions->NewShader = st_new_shader; 247 functions->NewShaderProgram = st_new_shader_program; 248 functions->LinkShader = st_link_shader; 249 } 250