X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=effect_chain.cpp;h=6b7a857242e0572c7be6d66afe6026734ec99c6c;hp=bd039b0113e662a9279976a3d01ed43e2a406102;hb=1f1da18ac6acec9e16e66441160b3949173f1db3;hpb=572e7aaa57028d7eda4bc445a6249637134a2b02 diff --git a/effect_chain.cpp b/effect_chain.cpp index bd039b0..6b7a857 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -1,33 +1,34 @@ #define GL_GLEXT_PROTOTYPES 1 -#include +#include +#include +#include #include +#include +#include +#include #include -#include -#include -#include - #include #include #include #include -#include "util.h" -#include "effect_chain.h" -#include "gamma_expansion_effect.h" -#include "gamma_compression_effect.h" -#include "colorspace_conversion_effect.h" -#include "alpha_multiplication_effect.h" #include "alpha_division_effect.h" +#include "alpha_multiplication_effect.h" +#include "colorspace_conversion_effect.h" #include "dither_effect.h" -#include "input.h" +#include "effect.h" +#include "effect_chain.h" +#include "gamma_compression_effect.h" +#include "gamma_expansion_effect.h" #include "init.h" +#include "input.h" +#include "util.h" EffectChain::EffectChain(float aspect_nom, float aspect_denom) : aspect_nom(aspect_nom), aspect_denom(aspect_denom), dither_effect(NULL), - fbo(0), num_dither_bits(0), finalized(false) {} @@ -46,13 +47,11 @@ EffectChain::~EffectChain() glDeleteShader(phases[i]->fragment_shader); delete phases[i]; } - if (fbo != 0) { - glDeleteFramebuffers(1, &fbo); - } } Input *EffectChain::add_input(Input *input) { + assert(!finalized); inputs.push_back(input); add_node(input); return input; @@ -60,12 +59,17 @@ Input *EffectChain::add_input(Input *input) void EffectChain::add_output(const ImageFormat &format, OutputAlphaFormat alpha_format) { + assert(!finalized); output_format = format; output_alpha_format = alpha_format; } Node *EffectChain::add_node(Effect *effect) { + for (unsigned i = 0; i < nodes.size(); ++i) { + assert(nodes[i]->effect != effect); + } + char effect_id[256]; sprintf(effect_id, "eff%u", (unsigned)nodes.size()); @@ -155,6 +159,7 @@ void EffectChain::find_all_nonlinear_inputs(Node *node, std::vector *non Effect *EffectChain::add_effect(Effect *effect, const std::vector &inputs) { + assert(!finalized); assert(inputs.size() == effect->num_inputs()); Node *node = add_node(effect); for (unsigned i = 0; i < inputs.size(); ++i) { @@ -782,6 +787,7 @@ void EffectChain::find_color_spaces_for_inputs() case Effect::OUTPUT_POSTMULTIPLIED_ALPHA: node->output_alpha_type = ALPHA_POSTMULTIPLIED; break; + case Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK: case Effect::DONT_CARE_ALPHA_TYPE: default: assert(false); @@ -894,6 +900,7 @@ void EffectChain::propagate_alpha() // whether to divide away the old alpha or not. Effect::AlphaHandling alpha_handling = node->effect->alpha_handling(); assert(alpha_handling == Effect::INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA || + alpha_handling == Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK || alpha_handling == Effect::DONT_CARE_ALPHA_TYPE); // If the node has multiple inputs, check that they are all valid and @@ -933,16 +940,16 @@ void EffectChain::propagate_alpha() continue; } - if (alpha_handling == Effect::INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA) { + if (alpha_handling == Effect::INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA || + alpha_handling == Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK) { // If the effect has asked for premultiplied alpha, check that it has got it. if (any_postmultiplied) { node->output_alpha_type = ALPHA_INVALID; + } else if (!any_premultiplied && + alpha_handling == Effect::INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK) { + // Blank input alpha, and the effect preserves blank alpha. + node->output_alpha_type = ALPHA_BLANK; } else { - // In some rare cases, it might be advantageous to say - // that blank input alpha yields blank output alpha. - // However, this would cause a more complex Effect interface - // an effect would need to guarantee that it doesn't mess with - // blank alpha), so this is the simplest. node->output_alpha_type = ALPHA_PREMULTIPLIED; } } else { @@ -1426,8 +1433,6 @@ void EffectChain::finalize() // since otherwise this turns into an (albeit simple) // register allocation problem. if (phases.size() > 1) { - glGenFramebuffers(1, &fbo); - for (unsigned i = 0; i < phases.size() - 1; ++i) { inform_input_sizes(phases[i]); find_output_size(phases[i]); @@ -1466,6 +1471,7 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height // Save original viewport. GLuint x = 0, y = 0; + GLuint fbo = 0; if (width == 0 && height == 0) { GLint viewport[4]; @@ -1492,6 +1498,8 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height glLoadIdentity(); if (phases.size() > 1) { + glGenFramebuffers(1, &fbo); + check_error(); glBindFramebuffer(GL_FRAMEBUFFER, fbo); check_error(); } @@ -1555,6 +1563,8 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height // Last phase goes to the output the user specified. glBindFramebuffer(GL_FRAMEBUFFER, dest_fbo); check_error(); + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + assert(status == GL_FRAMEBUFFER_COMPLETE); glViewport(x, y, width, height); if (dither_effect != NULL) { CHECK(dither_effect->set_int("output_width", width)); @@ -1569,6 +1579,8 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height output_node->output_texture, 0); check_error(); + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + assert(status == GL_FRAMEBUFFER_COMPLETE); glViewport(0, 0, phases[phase]->output_width, phases[phase]->output_height); } @@ -1603,4 +1615,12 @@ void EffectChain::render_to_fbo(GLuint dest_fbo, unsigned width, unsigned height node->effect->clear_gl_state(); } } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + check_error(); + + if (fbo != 0) { + glDeleteFramebuffers(1, &fbo); + check_error(); + } }