/** * Translate TGSI shader into an svga shader variant. */ static enum pipe_error compile_fs(struct svga_context *svga, struct svga_fragment_shader *fs, const struct svga_fs_compile_key *key, struct svga_shader_variant **out_variant) { struct svga_shader_variant *variant; enum pipe_error ret = PIPE_ERROR; variant = svga_translate_fragment_program( fs, key ); if (variant == NULL) { debug_printf("Failed to compile fragment shader," " using dummy shader instead.\n"); variant = get_compiled_dummy_shader(fs, key); if (!variant) { ret = PIPE_ERROR; goto fail; } } if (variant->nr_tokens * sizeof(variant->tokens[0]) + sizeof(SVGA3dCmdDefineShader) + sizeof(SVGA3dCmdHeader) >= SVGA_CB_MAX_COMMAND_SIZE) { /* too big, use dummy shader */ debug_printf("Shader too large (%lu bytes)," " using dummy shader instead.\n", (unsigned long ) variant->nr_tokens * sizeof(variant->tokens[0])); variant = get_compiled_dummy_shader(fs, key); if (!variant) { ret = PIPE_ERROR; goto fail; } } ret = svga_define_shader(svga, SVGA3D_SHADERTYPE_PS, variant); if (ret != PIPE_OK) goto fail; *out_variant = variant; /* insert variants at head of linked list */ variant->next = fs->base.variants; fs->base.variants = variant; return PIPE_OK; fail: if (variant) { svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_PS, variant); } return ret; }
/** * Replace the given shader's instruction with a simple constant-color * shader. We use this when normal shader translation fails. */ static struct svga_shader_variant * get_compiled_dummy_shader(struct svga_fragment_shader *fs, const struct svga_fs_compile_key *key) { const struct tgsi_token *dummy = get_dummy_fragment_shader(); struct svga_shader_variant *variant; if (!dummy) { return NULL; } FREE((void *) fs->base.tokens); fs->base.tokens = dummy; variant = svga_translate_fragment_program(fs, key); return variant; }
static enum pipe_error compile_fs( struct svga_context *svga, struct svga_fragment_shader *fs, const struct svga_fs_compile_key *key, struct svga_shader_result **out_result ) { struct svga_shader_result *result; enum pipe_error ret = PIPE_ERROR; result = svga_translate_fragment_program( fs, key ); if (result == NULL) { ret = PIPE_ERROR_OUT_OF_MEMORY; goto fail; } result->id = util_bitmask_add(svga->fs_bm); if(result->id == UTIL_BITMASK_INVALID_INDEX) { ret = PIPE_ERROR_OUT_OF_MEMORY; goto fail; } ret = SVGA3D_DefineShader(svga->swc, result->id, SVGA3D_SHADERTYPE_PS, result->tokens, result->nr_tokens * sizeof result->tokens[0]); if (ret) goto fail; *out_result = result; result->next = fs->base.results; fs->base.results = result; return PIPE_OK; fail: if (result) { if (result->id != UTIL_BITMASK_INVALID_INDEX) util_bitmask_clear( svga->fs_bm, result->id ); svga_destroy_shader_result( result ); } return ret; }