static void svga_delete_gs_state(struct pipe_context *pipe, void *shader) { struct svga_context *svga = svga_context(pipe); struct svga_geometry_shader *gs = (struct svga_geometry_shader *)shader; struct svga_geometry_shader *next_gs; struct svga_shader_variant *variant, *tmp; enum pipe_error ret; svga_hwtnl_flush_retry(svga); /* Start deletion from the original geometry shader state */ if (gs->base.parent != NULL) gs = (struct svga_geometry_shader *)gs->base.parent; /* Free the list of geometry shaders */ while (gs) { next_gs = (struct svga_geometry_shader *)gs->base.next; if (gs->base.stream_output != NULL) svga_delete_stream_output(svga, gs->base.stream_output); draw_delete_geometry_shader(svga->swtnl.draw, gs->draw_shader); for (variant = gs->base.variants; variant; variant = tmp) { tmp = variant->next; /* Check if deleting currently bound shader */ if (variant == svga->state.hw_draw.gs) { ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_GS, NULL); if (ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_GS, NULL); assert(ret == PIPE_OK); } svga->state.hw_draw.gs = NULL; } ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_GS, variant); if (ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_GS, variant); assert(ret == PIPE_OK); } } FREE((void *)gs->base.tokens); FREE(gs); gs = next_gs; } }
static void svga_delete_vs_state(struct pipe_context *pipe, void *shader) { struct svga_context *svga = svga_context(pipe); struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader; struct svga_shader_variant *variant, *tmp; enum pipe_error ret; svga_hwtnl_flush_retry(svga); assert(vs->base.parent == NULL); /* Check if there is a generated geometry shader to go with this * vertex shader. If there is, then delete the geometry shader as well. */ if (vs->gs != NULL) { svga->pipe.delete_gs_state(&svga->pipe, vs->gs); } if (vs->base.stream_output != NULL) svga_delete_stream_output(svga, vs->base.stream_output); draw_delete_vertex_shader(svga->swtnl.draw, vs->draw_shader); for (variant = vs->base.variants; variant; variant = tmp) { tmp = variant->next; /* Check if deleting currently bound shader */ if (variant == svga->state.hw_draw.vs) { ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_VS, NULL); if (ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_VS, NULL); assert(ret == PIPE_OK); } svga->state.hw_draw.vs = NULL; } ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_VS, variant); if (ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_VS, variant); assert(ret == PIPE_OK); } } FREE((void *)vs->base.tokens); FREE(vs); }
/** * Translate TGSI shader into an svga shader variant. */ static enum pipe_error compile_gs(struct svga_context *svga, struct svga_geometry_shader *gs, const struct svga_compile_key *key, struct svga_shader_variant **out_variant) { struct svga_shader_variant *variant; enum pipe_error ret = PIPE_ERROR; variant = translate_geometry_program(svga, gs, key); if (!variant) { /* some problem during translation, try the dummy shader */ const struct tgsi_token *dummy = get_dummy_geometry_shader(); if (!dummy) { return PIPE_ERROR_OUT_OF_MEMORY; } debug_printf("Failed to compile geometry shader, using dummy shader instead.\n"); FREE((void *) gs->base.tokens); gs->base.tokens = dummy; variant = translate_geometry_program(svga, gs, key); if (!variant) { return PIPE_ERROR; } } ret = svga_define_shader(svga, SVGA3D_SHADERTYPE_GS, variant); if (ret != PIPE_OK) { svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_GS, variant); return ret; } *out_variant = variant; return PIPE_OK; }
/** * 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_compile_key *key, struct svga_shader_variant **out_variant) { struct svga_shader_variant *variant; enum pipe_error ret = PIPE_ERROR; variant = translate_fragment_program(svga, fs, key); if (variant == NULL) { debug_printf("Failed to compile fragment shader," " using dummy shader instead.\n"); variant = get_compiled_dummy_shader(svga, fs, key); } else if (svga_shader_too_large(svga, variant)) { /* too big, use dummy shader */ debug_printf("Shader too large (%u bytes)," " using dummy shader instead.\n", (unsigned) (variant->nr_tokens * sizeof(variant->tokens[0]))); /* Free the too-large variant */ svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_PS, variant); /* Use simple pass-through shader instead */ variant = get_compiled_dummy_shader(svga, fs, key); } if (!variant) { return PIPE_ERROR; } ret = svga_define_shader(svga, SVGA3D_SHADERTYPE_PS, variant); if (ret != PIPE_OK) { svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_PS, variant); return ret; } *out_variant = variant; /* insert variant at head of linked list */ variant->next = fs->base.variants; fs->base.variants = variant; return PIPE_OK; }
/** * 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; }