X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=effect_chain.cpp;h=3bc04a3d84a7b621f4af7b345dde1ad781b8224c;hp=64e3decdd5f5ac4403fe8afd1d8c6eeb73c44fcd;hb=af39090a8902411ffc0c89f296a0f8bde9229f60;hpb=72764bef4a33d18d4282887a188946261937ca8e diff --git a/effect_chain.cpp b/effect_chain.cpp index 64e3dec..3bc04a3 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -21,8 +21,29 @@ EffectChain::EffectChain(float aspect_nom, float aspect_denom) : aspect_nom(aspect_nom), aspect_denom(aspect_denom), + fbo(0), finalized(false) {} +EffectChain::~EffectChain() +{ + for (unsigned i = 0; i < nodes.size(); ++i) { + if (nodes[i]->output_texture != 0) { + glDeleteTextures(1, &nodes[i]->output_texture); + } + delete nodes[i]->effect; + delete nodes[i]; + } + for (unsigned i = 0; i < phases.size(); ++i) { + glDeleteProgram(phases[i]->glsl_program_num); + glDeleteShader(phases[i]->vertex_shader); + glDeleteShader(phases[i]->fragment_shader); + delete phases[i]; + } + if (fbo != 0) { + glDeleteFramebuffers(1, &fbo); + } +} + Input *EffectChain::add_input(Input *input) { inputs.push_back(input); @@ -49,6 +70,7 @@ Node *EffectChain::add_node(Effect *effect) node->effect_id = effect_id; node->output_color_space = COLORSPACE_INVALID; node->output_gamma_curve = GAMMA_INVALID; + node->output_texture = 0; nodes.push_back(node); node_map[effect] = node; @@ -267,6 +289,8 @@ Phase *EffectChain::compile_glsl_program( Phase *phase = new Phase; phase->glsl_program_num = glsl_program_num; + phase->vertex_shader = vs_obj; + phase->fragment_shader = fs_obj; phase->input_needs_mipmaps = input_needs_mipmaps; phase->inputs = true_inputs; phase->effects = effects; @@ -330,13 +354,27 @@ void EffectChain::construct_glsl_programs(Node *output) start_new_phase = true; } - if (deps[i]->outgoing_links.size() > 1 && deps[i]->effect->num_inputs() > 0) { - // More than one effect uses this as the input, - // and it is not a texture itself. - // The easiest thing to do (and probably also the safest - // performance-wise in most cases) is to bounce it to a texture - // and then let the next passes read from that. - start_new_phase = true; + if (deps[i]->outgoing_links.size() > 1) { + if (deps[i]->effect->num_inputs() > 0) { + // More than one effect uses this as the input, + // and it is not a texture itself. + // The easiest thing to do (and probably also the safest + // performance-wise in most cases) is to bounce it to a texture + // and then let the next passes read from that. + start_new_phase = true; + } else { + // For textures, we try to be slightly more clever; + // if none of our outputs need a bounce, we don't bounce + // but instead simply use the effect many times. + // + // Strictly speaking, we could bounce it for some outputs + // and use it directly for others, but the processing becomes + // somewhat simpler if the effect is only used in one such way. + for (unsigned j = 0; j < deps[i]->outgoing_links.size(); ++j) { + Node *rdep = deps[i]->outgoing_links[j]; + start_new_phase |= rdep->effect->needs_texture_bounce(); + } + } } if (deps[i]->effect->changes_output_size()) { @@ -726,6 +764,7 @@ void EffectChain::fix_output_color_space() conversion->effect->set_int("destination_space", output_format.color_space); conversion->output_color_space = output_format.color_space; connect_nodes(output, conversion); + propagate_gamma_and_color_space(); } }