1 /************************************************************************** 2 * 3 * Copyright 2007 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 #include "sp_context.h" 29 #include "sp_state.h" 30 #include "sp_fs.h" 31 #include "sp_texture.h" 32 33 #include "pipe/p_defines.h" 34 #include "util/u_memory.h" 35 #include "util/u_inlines.h" 36 #include "util/u_pstipple.h" 37 #include "draw/draw_context.h" 38 #include "draw/draw_vs.h" 39 #include "draw/draw_gs.h" 40 #include "tgsi/tgsi_dump.h" 41 #include "tgsi/tgsi_scan.h" 42 #include "tgsi/tgsi_parse.h" 43 44 45 /** 46 * Create a new fragment shader variant. 47 */ 48 static struct sp_fragment_shader_variant * 49 create_fs_variant(struct softpipe_context *softpipe, 50 struct sp_fragment_shader *fs, 51 const struct sp_fragment_shader_variant_key *key) 52 { 53 struct sp_fragment_shader_variant *var; 54 struct pipe_shader_state *stipple_fs = NULL, *curfs = &fs->shader; 55 unsigned unit = 0; 56 57 #if DO_PSTIPPLE_IN_HELPER_MODULE 58 if (key->polygon_stipple) { 59 /* get new shader that implements polygon stippling */ 60 stipple_fs = util_pstipple_create_fragment_shader(&softpipe->pipe, 61 curfs, &unit); 62 curfs = stipple_fs; 63 } 64 #endif 65 66 /* codegen, create variant object */ 67 var = softpipe_create_fs_variant_exec(softpipe, curfs); 68 69 if (var) { 70 var->key = *key; 71 var->tokens = tgsi_dup_tokens(curfs->tokens); 72 var->stipple_sampler_unit = unit; 73 74 tgsi_scan_shader(var->tokens, &var->info); 75 76 /* See comments elsewhere about draw fragment shaders */ 77 #if 0 78 /* draw's fs state */ 79 var->draw_shader = draw_create_fragment_shader(softpipe->draw, 80 &fs->shader); 81 if (!var->draw_shader) { 82 var->delete(var); 83 FREE((void *) var->tokens); 84 return NULL; 85 } 86 #endif 87 88 /* insert variant into linked list */ 89 var->next = fs->variants; 90 fs->variants = var; 91 } 92 93 if (stipple_fs) { 94 FREE((void *) stipple_fs->tokens); 95 FREE(stipple_fs); 96 } 97 98 return var; 99 } 100 101 102 struct sp_fragment_shader_variant * 103 softpipe_find_fs_variant(struct softpipe_context *sp, 104 struct sp_fragment_shader *fs, 105 const struct sp_fragment_shader_variant_key *key) 106 { 107 struct sp_fragment_shader_variant *var; 108 109 for (var = fs->variants; var; var = var->next) { 110 if (memcmp(&var->key, key, sizeof(*key)) == 0) { 111 /* found it */ 112 return var; 113 } 114 } 115 116 return create_fs_variant(sp, fs, key); 117 } 118 119 120 static void * 121 softpipe_create_fs_state(struct pipe_context *pipe, 122 const struct pipe_shader_state *templ) 123 { 124 struct softpipe_context *softpipe = softpipe_context(pipe); 125 struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader); 126 127 /* debug */ 128 if (softpipe->dump_fs) 129 tgsi_dump(templ->tokens, 0); 130 131 /* we need to keep a local copy of the tokens */ 132 state->shader.tokens = tgsi_dup_tokens(templ->tokens); 133 134 /* draw's fs state */ 135 state->draw_shader = draw_create_fragment_shader(softpipe->draw, 136 &state->shader); 137 if (!state->draw_shader) { 138 FREE((void *) state->shader.tokens); 139 FREE(state); 140 return NULL; 141 } 142 143 return state; 144 } 145 146 147 static void 148 softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) 149 { 150 struct softpipe_context *softpipe = softpipe_context(pipe); 151 struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs; 152 153 if (softpipe->fs == fs) 154 return; 155 156 draw_flush(softpipe->draw); 157 158 softpipe->fs = fs; 159 160 /* This depends on the current fragment shader and must always be 161 * re-validated before use. 162 */ 163 softpipe->fs_variant = NULL; 164 165 if (state) 166 draw_bind_fragment_shader(softpipe->draw, 167 state->draw_shader); 168 else 169 draw_bind_fragment_shader(softpipe->draw, NULL); 170 171 softpipe->dirty |= SP_NEW_FS; 172 } 173 174 175 static void 176 softpipe_delete_fs_state(struct pipe_context *pipe, void *fs) 177 { 178 struct softpipe_context *softpipe = softpipe_context(pipe); 179 struct sp_fragment_shader *state = fs; 180 struct sp_fragment_shader_variant *var, *next_var; 181 182 assert(fs != softpipe->fs); 183 184 /* delete variants */ 185 for (var = state->variants; var; var = next_var) { 186 next_var = var->next; 187 188 assert(var != softpipe->fs_variant); 189 190 /* See comments elsewhere about draw fragment shaders */ 191 #if 0 192 draw_delete_fragment_shader(softpipe->draw, var->draw_shader); 193 #endif 194 195 var->delete(var, softpipe->fs_machine); 196 } 197 198 draw_delete_fragment_shader(softpipe->draw, state->draw_shader); 199 200 FREE((void *) state->shader.tokens); 201 FREE(state); 202 } 203 204 205 static void * 206 softpipe_create_vs_state(struct pipe_context *pipe, 207 const struct pipe_shader_state *templ) 208 { 209 struct softpipe_context *softpipe = softpipe_context(pipe); 210 struct sp_vertex_shader *state; 211 212 state = CALLOC_STRUCT(sp_vertex_shader); 213 if (state == NULL ) 214 goto fail; 215 216 /* copy shader tokens, the ones passed in will go away. 217 */ 218 state->shader.tokens = tgsi_dup_tokens(templ->tokens); 219 if (state->shader.tokens == NULL) 220 goto fail; 221 222 state->draw_data = draw_create_vertex_shader(softpipe->draw, templ); 223 if (state->draw_data == NULL) 224 goto fail; 225 226 state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER]; 227 228 return state; 229 230 fail: 231 if (state) { 232 FREE( (void *)state->shader.tokens ); 233 FREE( state->draw_data ); 234 FREE( state ); 235 } 236 return NULL; 237 } 238 239 240 static void 241 softpipe_bind_vs_state(struct pipe_context *pipe, void *vs) 242 { 243 struct softpipe_context *softpipe = softpipe_context(pipe); 244 245 softpipe->vs = (struct sp_vertex_shader *) vs; 246 247 draw_bind_vertex_shader(softpipe->draw, 248 (softpipe->vs ? softpipe->vs->draw_data : NULL)); 249 250 softpipe->dirty |= SP_NEW_VS; 251 } 252 253 254 static void 255 softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) 256 { 257 struct softpipe_context *softpipe = softpipe_context(pipe); 258 259 struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs; 260 261 draw_delete_vertex_shader(softpipe->draw, state->draw_data); 262 FREE( (void *)state->shader.tokens ); 263 FREE( state ); 264 } 265 266 267 static void * 268 softpipe_create_gs_state(struct pipe_context *pipe, 269 const struct pipe_shader_state *templ) 270 { 271 struct softpipe_context *softpipe = softpipe_context(pipe); 272 struct sp_geometry_shader *state; 273 274 state = CALLOC_STRUCT(sp_geometry_shader); 275 if (state == NULL ) 276 goto fail; 277 278 /* debug */ 279 if (softpipe->dump_gs) 280 tgsi_dump(templ->tokens, 0); 281 282 /* copy shader tokens, the ones passed in will go away. 283 */ 284 state->shader.tokens = tgsi_dup_tokens(templ->tokens); 285 if (state->shader.tokens == NULL) 286 goto fail; 287 288 state->draw_data = draw_create_geometry_shader(softpipe->draw, templ); 289 if (state->draw_data == NULL) 290 goto fail; 291 292 state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER]; 293 294 return state; 295 296 fail: 297 if (state) { 298 FREE( (void *)state->shader.tokens ); 299 FREE( state->draw_data ); 300 FREE( state ); 301 } 302 return NULL; 303 } 304 305 306 static void 307 softpipe_bind_gs_state(struct pipe_context *pipe, void *gs) 308 { 309 struct softpipe_context *softpipe = softpipe_context(pipe); 310 311 softpipe->gs = (struct sp_geometry_shader *)gs; 312 313 draw_bind_geometry_shader(softpipe->draw, 314 (softpipe->gs ? softpipe->gs->draw_data : NULL)); 315 316 softpipe->dirty |= SP_NEW_GS; 317 } 318 319 320 static void 321 softpipe_delete_gs_state(struct pipe_context *pipe, void *gs) 322 { 323 struct softpipe_context *softpipe = softpipe_context(pipe); 324 325 struct sp_geometry_shader *state = 326 (struct sp_geometry_shader *)gs; 327 328 draw_delete_geometry_shader(softpipe->draw, 329 (state) ? state->draw_data : 0); 330 331 FREE((void *) state->shader.tokens); 332 FREE(state); 333 } 334 335 336 static void 337 softpipe_set_constant_buffer(struct pipe_context *pipe, 338 uint shader, uint index, 339 struct pipe_constant_buffer *cb) 340 { 341 struct softpipe_context *softpipe = softpipe_context(pipe); 342 struct pipe_resource *constants = cb ? cb->buffer : NULL; 343 unsigned size; 344 const void *data; 345 346 if (cb && cb->user_buffer) { 347 constants = softpipe_user_buffer_create(pipe->screen, 348 (void *) cb->user_buffer, 349 cb->buffer_size, 350 PIPE_BIND_CONSTANT_BUFFER); 351 } 352 353 size = constants ? constants->width0 : 0; 354 data = constants ? softpipe_resource(constants)->data : NULL; 355 356 assert(shader < PIPE_SHADER_TYPES); 357 358 draw_flush(softpipe->draw); 359 360 /* note: reference counting */ 361 pipe_resource_reference(&softpipe->constants[shader][index], constants); 362 363 if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { 364 draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size); 365 } 366 367 softpipe->mapped_constants[shader][index] = data; 368 softpipe->const_buffer_size[shader][index] = size; 369 370 softpipe->dirty |= SP_NEW_CONSTANTS; 371 372 if (cb && cb->user_buffer) { 373 pipe_resource_reference(&constants, NULL); 374 } 375 } 376 377 378 void 379 softpipe_init_shader_funcs(struct pipe_context *pipe) 380 { 381 pipe->create_fs_state = softpipe_create_fs_state; 382 pipe->bind_fs_state = softpipe_bind_fs_state; 383 pipe->delete_fs_state = softpipe_delete_fs_state; 384 385 pipe->create_vs_state = softpipe_create_vs_state; 386 pipe->bind_vs_state = softpipe_bind_vs_state; 387 pipe->delete_vs_state = softpipe_delete_vs_state; 388 389 pipe->create_gs_state = softpipe_create_gs_state; 390 pipe->bind_gs_state = softpipe_bind_gs_state; 391 pipe->delete_gs_state = softpipe_delete_gs_state; 392 393 pipe->set_constant_buffer = softpipe_set_constant_buffer; 394 } 395