void st_delete_program(GLcontext *ctx, struct gl_program *prog) { struct st_context *st = st_context(ctx); switch( prog->Target ) { case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; if (stvp->driver_shader) { cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); stvp->driver_shader = NULL; } if (stvp->draw_shader) { #if FEATURE_feedback || FEATURE_drawpix /* this would only have been allocated for the RasterPos path */ draw_delete_vertex_shader(st->draw, stvp->draw_shader); stvp->draw_shader = NULL; #endif } if (stvp->state.tokens) { st_free_tokens(stvp->state.tokens); stvp->state.tokens = NULL; } } break; case GL_FRAGMENT_PROGRAM_ARB: { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; if (stfp->driver_shader) { cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); stfp->driver_shader = NULL; } if (stfp->state.tokens) { st_free_tokens(stfp->state.tokens); stfp->state.tokens = NULL; } if (stfp->bitmap_program) { struct gl_program *prg = &stfp->bitmap_program->Base.Base; _mesa_reference_program(ctx, &prg, NULL); stfp->bitmap_program = NULL; } st_free_translated_vertex_programs(st, stfp->vertex_programs); } break; default: assert(0); /* problem */ } /* delete base class */ _mesa_delete_program( ctx, prog ); }
static void st_program_string_notify( GLcontext *ctx, GLenum target, struct gl_program *prog ) { struct st_context *st = st_context(ctx); if (target == GL_FRAGMENT_PROGRAM_ARB) { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; stfp->serialNo++; if (stfp->driver_shader) { cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); stfp->driver_shader = NULL; } if (stfp->state.tokens) { st_free_tokens(stfp->state.tokens); stfp->state.tokens = NULL; } stfp->param_state = stfp->Base.Base.Parameters->StateFlags; if (st->fp == stfp) st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; } else if (target == GL_VERTEX_PROGRAM_ARB) { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; stvp->serialNo++; if (stvp->driver_shader) { cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); stvp->driver_shader = NULL; } if (stvp->draw_shader) { #if FEATURE_feedback || FEATURE_drawpix /* this would only have been allocated for the RasterPos path */ draw_delete_vertex_shader(st->draw, stvp->draw_shader); stvp->draw_shader = NULL; #endif } if (stvp->state.tokens) { st_free_tokens(stvp->state.tokens); stvp->state.tokens = NULL; } stvp->param_state = stvp->Base.Base.Parameters->StateFlags; if (st->vp == stvp) st->dirty.st |= ST_NEW_VERTEX_PROGRAM; } }
/** * Called via ctx->Driver.DeleteProgram() */ static void st_delete_program(struct gl_context *ctx, struct gl_program *prog) { struct st_context *st = st_context(ctx); switch( prog->Target ) { case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; st_release_vp_variants( st, stvp ); if (stvp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(stvp->glsl_to_tgsi); } break; case MESA_GEOMETRY_PROGRAM: { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; st_release_gp_variants(st, stgp); if (stgp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(stgp->glsl_to_tgsi); if (stgp->tgsi.tokens) { st_free_tokens((void *) stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } } break; case GL_FRAGMENT_PROGRAM_ARB: { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; st_release_fp_variants(st, stfp); if (stfp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi); if (stfp->tgsi.tokens) { st_free_tokens(stfp->tgsi.tokens); stfp->tgsi.tokens = NULL; } } break; default: assert(0); /* problem */ } /* delete base class */ _mesa_delete_program( ctx, prog ); }
/** * Called via ctx->Driver.ProgramStringNotify() * Called when the program's text/code is changed. We have to free * all shader variants and corresponding gallium shaders when this happens. */ static GLboolean st_program_string_notify( struct gl_context *ctx, GLenum target, struct gl_program *prog ) { struct st_context *st = st_context(ctx); if (target == GL_FRAGMENT_PROGRAM_ARB) { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; st_release_fp_variants(st, stfp); if (stfp->tgsi.tokens) { st_free_tokens(stfp->tgsi.tokens); stfp->tgsi.tokens = NULL; } if (st->fp == stfp) st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; } else if (target == MESA_GEOMETRY_PROGRAM) { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; st_release_gp_variants(st, stgp); if (stgp->tgsi.tokens) { st_free_tokens((void *) stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } if (st->gp == stgp) st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM; } else if (target == GL_VERTEX_PROGRAM_ARB) { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; st_release_vp_variants( st, stvp ); if (st->vp == stvp) st->dirty.st |= ST_NEW_VERTEX_PROGRAM; } /* XXX check if program is legal, within limits */ return GL_TRUE; }
/** * Delete a fragment program variant. Note the caller must unlink * the variant from the linked list. */ static void delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv) { if (fpv->driver_shader) cso_delete_fragment_shader(st->cso_context, fpv->driver_shader); if (fpv->parameters) _mesa_free_parameter_list(fpv->parameters); if (fpv->tgsi.tokens) st_free_tokens(fpv->tgsi.tokens); free(fpv); }
/** * Delete a vertex program variant. Note the caller must unlink * the variant from the linked list. */ static void delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv) { if (vpv->driver_shader) cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); if (vpv->draw_shader) draw_delete_vertex_shader( st->draw, vpv->draw_shader ); if (vpv->tgsi.tokens) st_free_tokens(vpv->tgsi.tokens); free( vpv ); }
/** * Delete a vertex program variant. Note the caller must unlink * the variant from the linked list. */ static void delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv) { if (vpv->driver_shader) cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); #if FEATURE_feedback || FEATURE_rastpos if (vpv->draw_shader) draw_delete_vertex_shader( st->draw, vpv->draw_shader ); #endif if (vpv->tgsi.tokens) st_free_tokens(vpv->tgsi.tokens); FREE( vpv ); }
/** * Translate a geometry program to create a new variant. */ static struct st_gp_variant * st_translate_geometry_program(struct st_context *st, struct st_geometry_program *stgp, const struct st_gp_variant_key *key) { GLuint inputMapping[GEOM_ATTRIB_MAX]; GLuint outputMapping[GEOM_RESULT_MAX]; struct pipe_context *pipe = st->pipe; enum pipe_error error; GLuint attr; const GLbitfield inputsRead = stgp->Base.Base.InputsRead; GLuint vslot = 0; GLuint num_generic = 0; uint gs_num_inputs = 0; uint gs_builtin_inputs = 0; uint gs_array_offset = 0; ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; uint gs_num_outputs = 0; GLint i; GLuint maxSlot = 0; struct ureg_program *ureg; struct st_gp_variant *gpv; gpv = CALLOC_STRUCT(st_gp_variant); if (!gpv) return NULL; _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING); ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); if (ureg == NULL) { FREE(gpv); return NULL; } /* which vertex output goes to the first geometry input */ vslot = 0; memset(inputMapping, 0, sizeof(inputMapping)); memset(outputMapping, 0, sizeof(outputMapping)); /* * Convert Mesa program inputs to TGSI input register semantics. */ for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) { if (inputsRead & (1 << attr)) { const GLuint slot = gs_num_inputs; gs_num_inputs++; inputMapping[attr] = slot; stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs; stgp->input_to_index[attr] = vslot; stgp->index_to_input[vslot] = attr; ++vslot; if (attr != GEOM_ATTRIB_PRIMITIVE_ID) { gs_array_offset += 2; } else ++gs_builtin_inputs; #if 0 debug_printf("input map at %d = %d\n", slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); #endif switch (attr) { case GEOM_ATTRIB_PRIMITIVE_ID: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; stgp->input_semantic_index[slot] = 0; break; case GEOM_ATTRIB_POSITION: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; stgp->input_semantic_index[slot] = 0; break; case GEOM_ATTRIB_COLOR0: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 0; break; case GEOM_ATTRIB_COLOR1: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 1; break; case GEOM_ATTRIB_FOG_FRAG_COORD: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; stgp->input_semantic_index[slot] = 0; break; case GEOM_ATTRIB_TEX_COORD: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = num_generic++; break; case GEOM_ATTRIB_VAR0: /* fall-through */ default: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = num_generic++; } } } /* initialize output semantics to defaults */ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[i] = 0; } num_generic = 0; /* * Determine number of outputs, the (default) output register * mapping and the semantic information for each output. */ for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) { GLuint slot; slot = gs_num_outputs; gs_num_outputs++; outputMapping[attr] = slot; switch (attr) { case GEOM_RESULT_POS: assert(slot == 0); gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_COL0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_COL1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 1; break; case GEOM_RESULT_SCOL0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_SCOL1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 1; break; case GEOM_RESULT_FOGC: gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_PSIZ: gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; gs_output_semantic_index[slot] = 0; break; case GEOM_RESULT_TEX0: case GEOM_RESULT_TEX1: case GEOM_RESULT_TEX2: case GEOM_RESULT_TEX3: case GEOM_RESULT_TEX4: case GEOM_RESULT_TEX5: case GEOM_RESULT_TEX6: case GEOM_RESULT_TEX7: /* fall-through */ case GEOM_RESULT_VAR0: /* fall-through */ default: assert(slot < Elements(gs_output_semantic_name)); /* use default semantic info */ gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[slot] = num_generic++; } } } assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION); /* find max output slot referenced to compute gs_num_outputs */ for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) maxSlot = outputMapping[attr]; } gs_num_outputs = maxSlot + 1; #if 0 /* debug */ { GLuint i; printf("outputMapping? %d\n", outputMapping ? 1 : 0); if (outputMapping) { printf("attr -> slot\n"); for (i = 0; i < 16; i++) { printf(" %2d %3d\n", i, outputMapping[i]); } } printf("slot sem_name sem_index\n"); for (i = 0; i < gs_num_outputs; i++) { printf(" %2d %d %d\n", i, gs_output_semantic_name[i], gs_output_semantic_index[i]); } } #endif /* free old shader state, if any */ if (stgp->tgsi.tokens) { st_free_tokens(stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); error = st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_GEOMETRY, ureg, &stgp->Base.Base, /* inputs */ gs_num_inputs, inputMapping, stgp->input_semantic_name, stgp->input_semantic_index, NULL, /* outputs */ gs_num_outputs, outputMapping, gs_output_semantic_name, gs_output_semantic_index, FALSE); stgp->num_inputs = gs_num_inputs; stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); /* fill in new variant */ gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); gpv->key = *key; if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); debug_printf("\n"); } if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump(stgp->tgsi.tokens, 0); debug_printf("\n"); } return gpv; }