diff --git a/effects/effect.cpp b/effects/effect.cpp index a56c961e5..99f9a1853 100644 --- a/effects/effect.cpp +++ b/effects/effect.cpp @@ -37,6 +37,7 @@ #include #include #include +#include QVector video_effect_names; QVector audio_effect_names; @@ -96,7 +97,10 @@ Effect::Effect(Clip* c, int t, int i) : id(i), enable_image(false), enable_opengl(false), - iterations(1) + iterations(1), + isOpen(false), + glslProgram(NULL), + bound(false) { container = new CollapsibleWidget(); if (type == EFFECT_TYPE_VIDEO) { @@ -113,6 +117,10 @@ Effect::Effect(Clip* c, int t, int i) : } Effect::~Effect() { + if (isOpen) { + close(); + } + for (int i=0;iaddShaderFromSourceFile(QOpenGLShader::Vertex, vertPath); + if (!fragPath.isEmpty()) glslProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, fragPath); + glslProgram->link(); + isOpen = true; + } +} + +void Effect::close() { + if (!isOpen) { + qDebug() << "[WARNING] Tried to close an effect that was already closed"; + } else { + delete glslProgram; + } + glslProgram = NULL; + isOpen = false; +} + +void Effect::startEffect() { + if (!isOpen) { + open(); + qDebug() << "[WARNING] Tried to start a closed effect - opening"; + } + bound = glslProgram->bind(); +} + +void Effect::endEffect() { + if (bound) glslProgram->release(); + bound = false; +} + int Effect::getIterations() { return iterations; } @@ -311,7 +358,6 @@ Effect* Effect::copy(Clip* c) { void Effect::process_image(double, uint8_t*, int, int) {} void Effect::process_gl(double, GLTextureCoords&) {} void Effect::process_audio(double, double, quint8*, int, int) {} -void Effect::clean_gl() {} /* Effect Row Definitions */ @@ -542,7 +588,7 @@ void EffectField::get_keyframe_data(double timecode, int &before, int &after, do } void EffectField::validate_keyframe_data(double timecode) { - if (parent_row->isKeyframing()) { + if (parent_row->isKeyframing() && keyframe_data.size() > 0) { int before_keyframe; int after_keyframe; double progress; diff --git a/effects/effect.h b/effects/effect.h index c16d7d142..cf4e6bb8c 100644 --- a/effects/effect.h +++ b/effects/effect.h @@ -192,6 +192,12 @@ public: void load(QXmlStreamReader& stream); void save(QXmlStreamWriter& stream); + // glsl handling + void open(); + void close(); + void startEffect(); + void endEffect(); + bool enable_image; bool enable_opengl; @@ -202,15 +208,20 @@ public: virtual void process_image(double timecode, uint8_t* data, int width, int height); virtual void process_gl(double timecode, GLTextureCoords& coords); - virtual void clean_gl(); virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); public slots: void field_changed(); +protected: + QOpenGLShaderProgram* glslProgram; + QString vertPath; + QString fragPath; + bool isOpen; private: QVector rows; QGridLayout* ui_layout; QWidget* ui; int iterations; + bool bound; }; #endif // EFFECT_H diff --git a/effects/video/boxblureffect.cpp b/effects/video/boxblureffect.cpp index 02ffad4d9..0fd82406c 100644 --- a/effects/video/boxblureffect.cpp +++ b/effects/video/boxblureffect.cpp @@ -2,7 +2,7 @@ #include "project/clip.h" -BoxBlurEffect::BoxBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_BOXBLUR_EFFECT), vert(QOpenGLShader::Vertex), frag(QOpenGLShader::Fragment) { +BoxBlurEffect::BoxBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_BOXBLUR_EFFECT) { enable_opengl = true; radius_val = add_row("Radius:")->add_field(EFFECT_FIELD_DOUBLE); @@ -19,11 +19,13 @@ BoxBlurEffect::BoxBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_BOXBL horiz_val->set_bool_value(true); vert_val->set_bool_value(true); - vert.compileSourceFile(":/shaders/common.vert"); + vertPath = ":/shaders/common.vert"; + fragPath = ":/shaders/boxblureffect.frag"; + /*vert.compileSourceFile(":/shaders/common.vert"); frag.compileSourceFile(":/shaders/boxblureffect.frag"); program.addShader(&vert); program.addShader(&frag); - program.link(); + program.link();*/ connect(radius_val, SIGNAL(changed()), this, SLOT(field_changed())); // connect(iteration_val, SIGNAL(changed()), this, SLOT(field_changed())); @@ -31,15 +33,9 @@ BoxBlurEffect::BoxBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_BOXBL connect(vert_val, SIGNAL(changed()), this, SLOT(field_changed())); } -void BoxBlurEffect::process_gl(double timecode, GLTextureCoords &coords) { - program.bind(); - - program.setUniformValue("resolution", parent_clip->getWidth(), parent_clip->getHeight()); - program.setUniformValue("radius", (GLfloat) radius_val->get_double_value(timecode)); - program.setUniformValue("horiz_blur", horiz_val->get_bool_value(timecode)); - program.setUniformValue("vert_blur", vert_val->get_bool_value(timecode)); -} - -void BoxBlurEffect::clean_gl() { - program.release(); +void BoxBlurEffect::process_gl(double timecode, GLTextureCoords&) { + glslProgram->setUniformValue("resolution", parent_clip->getWidth(), parent_clip->getHeight()); + glslProgram->setUniformValue("radius", (GLfloat) radius_val->get_double_value(timecode)); + glslProgram->setUniformValue("horiz_blur", horiz_val->get_bool_value(timecode)); + glslProgram->setUniformValue("vert_blur", vert_val->get_bool_value(timecode)); } diff --git a/effects/video/boxblureffect.h b/effects/video/boxblureffect.h index 73e800894..261964918 100644 --- a/effects/video/boxblureffect.h +++ b/effects/video/boxblureffect.h @@ -8,13 +8,8 @@ class BoxBlurEffect : public Effect public: BoxBlurEffect(Clip* c); - void process_gl(double timecode, GLTextureCoords &coords); - void clean_gl(); + void process_gl(double timecode, GLTextureCoords &coords); private: - QOpenGLShaderProgram program; - QOpenGLShader vert; - QOpenGLShader frag; - EffectField* radius_val; EffectField* iteration_val; EffectField* horiz_val; diff --git a/effects/video/chromakeyeffect.cpp b/effects/video/chromakeyeffect.cpp index bb3c09b1d..4a67b89fc 100644 --- a/effects/video/chromakeyeffect.cpp +++ b/effects/video/chromakeyeffect.cpp @@ -1,6 +1,6 @@ #include "chromakeyeffect.h" -ChromaKeyEffect::ChromaKeyEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_CHROMAKEY_EFFECT), vert(QOpenGLShader::Vertex), frag(QOpenGLShader::Fragment) { +ChromaKeyEffect::ChromaKeyEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_CHROMAKEY_EFFECT) { enable_opengl = true; color_field = add_row("Color:")->add_field(EFFECT_FIELD_COLOR); @@ -12,22 +12,14 @@ ChromaKeyEffect::ChromaKeyEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_C tolerance_field->set_double_minimum_value(0); tolerance_field->set_double_maximum_value(100); - vert.compileSourceFile(":/shaders/common.vert"); - frag.compileSourceFile(":/shaders/chromakeyeffect.frag"); - program.addShader(&vert); - program.addShader(&frag); - program.link(); + vertPath = ":/shaders/common.vert"; + fragPath = ":/shaders/chromakeyeffect.frag"; connect(color_field, SIGNAL(changed()), this, SLOT(field_changed())); connect(tolerance_field, SIGNAL(changed()), this, SLOT(field_changed())); } void ChromaKeyEffect::process_gl(double timecode, GLTextureCoords&) { - program.bind(); - program.setUniformValue("keyColor", color_field->get_color_value(timecode)); - program.setUniformValue("threshold", (GLfloat) (tolerance_field->get_double_value(timecode)*0.01)); -} - -void ChromaKeyEffect::clean_gl() { - program.release(); + glslProgram->setUniformValue("keyColor", color_field->get_color_value(timecode)); + glslProgram->setUniformValue("threshold", (GLfloat) (tolerance_field->get_double_value(timecode)*0.01)); } diff --git a/effects/video/chromakeyeffect.h b/effects/video/chromakeyeffect.h index 50c70cc58..6cc619185 100644 --- a/effects/video/chromakeyeffect.h +++ b/effects/video/chromakeyeffect.h @@ -7,13 +7,9 @@ class ChromaKeyEffect : public Effect { public: ChromaKeyEffect(Clip* c); void process_gl(double timecode, GLTextureCoords &coords); - void clean_gl(); private: EffectField* color_field; EffectField* tolerance_field; - QOpenGLShaderProgram program; - QOpenGLShader vert; - QOpenGLShader frag; }; #endif // CHROMAKEYEFFECT_H diff --git a/effects/video/gaussianblureffect.cpp b/effects/video/gaussianblureffect.cpp index ba88e11e4..62765e9ab 100644 --- a/effects/video/gaussianblureffect.cpp +++ b/effects/video/gaussianblureffect.cpp @@ -4,7 +4,7 @@ #include -GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_GAUSSIANBLUR_EFFECT), frag(QOpenGLShader::Fragment), vert(QOpenGLShader::Vertex) { +GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_GAUSSIANBLUR_EFFECT) { enable_opengl = true; radius_val = add_row("Radius:")->add_field(EFFECT_FIELD_DOUBLE); @@ -21,11 +21,8 @@ GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, V horiz_val->set_bool_value(true); vert_val->set_bool_value(true); - vert.compileSourceFile(":/shaders/common.vert"); - frag.compileSourceFile(":/shaders/gaussianblureffect.frag"); - program.addShader(&vert); - program.addShader(&frag); - program.link(); + vertPath = ":/shaders/common.vert"; + fragPath = ":/shaders/gaussianblureffect.frag"; connect(radius_val, SIGNAL(changed()), this, SLOT(field_changed())); connect(sigma_val, SIGNAL(changed()), this, SLOT(field_changed())); @@ -34,15 +31,9 @@ GaussianBlurEffect::GaussianBlurEffect(Clip *c) : Effect(c, EFFECT_TYPE_VIDEO, V } void GaussianBlurEffect::process_gl(double timecode, GLTextureCoords &coords) { - program.bind(); - - program.setUniformValue("resolution", parent_clip->getWidth(), parent_clip->getHeight()); - program.setUniformValue("radius", (GLfloat) radius_val->get_double_value(timecode)); - program.setUniformValue("sigma", (GLfloat) sigma_val->get_double_value(timecode)); - program.setUniformValue("horiz_blur", horiz_val->get_bool_value(timecode)); - program.setUniformValue("vert_blur", vert_val->get_bool_value(timecode)); -} - -void GaussianBlurEffect::clean_gl() { - program.release(); + glslProgram->setUniformValue("resolution", parent_clip->getWidth(), parent_clip->getHeight()); + glslProgram->setUniformValue("radius", (GLfloat) radius_val->get_double_value(timecode)); + glslProgram->setUniformValue("sigma", (GLfloat) sigma_val->get_double_value(timecode)); + glslProgram->setUniformValue("horiz_blur", horiz_val->get_bool_value(timecode)); + glslProgram->setUniformValue("vert_blur", vert_val->get_bool_value(timecode)); } diff --git a/effects/video/gaussianblureffect.h b/effects/video/gaussianblureffect.h index 2be320be8..0be35631c 100644 --- a/effects/video/gaussianblureffect.h +++ b/effects/video/gaussianblureffect.h @@ -8,12 +8,7 @@ class GaussianBlurEffect : public Effect public: GaussianBlurEffect(Clip* c); void process_gl(double timecode, GLTextureCoords &coords); - void clean_gl(); private: - QOpenGLShaderProgram program; - QOpenGLShader vert; - QOpenGLShader frag; - EffectField* radius_val; EffectField* sigma_val; EffectField* horiz_val; diff --git a/effects/video/inverteffect.cpp b/effects/video/inverteffect.cpp index 1d682fe72..8995c1d8c 100644 --- a/effects/video/inverteffect.cpp +++ b/effects/video/inverteffect.cpp @@ -9,7 +9,7 @@ #include #include -InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_EFFECT), vert(QOpenGLShader::Vertex), frag(QOpenGLShader::Fragment) { +InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_EFFECT) { enable_opengl = true; EffectRow* amount_row = add_row("Amount:"); @@ -22,18 +22,10 @@ InvertEffect::InvertEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_INVERT_ connect(amount_val, SIGNAL(changed()), this, SLOT(field_changed())); - vert.compileSourceFile(":/shaders/common.vert"); - frag.compileSourceFile(":/shaders/inverteffect.frag"); - program.addShader(&vert); - program.addShader(&frag); - program.link(); + vertPath = ":/shaders/common.vert"; + fragPath = ":/shaders/inverteffect.frag"; } void InvertEffect::process_gl(double timecode, GLTextureCoords&) { - program.bind(); - program.setUniformValue("amount_val", (GLfloat) (amount_val->get_double_value(timecode)*0.01)); -} - -void InvertEffect::clean_gl() { - program.release(); + glslProgram->setUniformValue("amount_val", (GLfloat) (amount_val->get_double_value(timecode)*0.01)); } diff --git a/effects/video/inverteffect.h b/effects/video/inverteffect.h index 47743810a..1d3aa3ff7 100644 --- a/effects/video/inverteffect.h +++ b/effects/video/inverteffect.h @@ -8,12 +8,8 @@ class InvertEffect : public Effect { public: InvertEffect(Clip* c); void process_gl(double timecode, GLTextureCoords& coords); - void clean_gl(); private: EffectField* amount_val; - QOpenGLShader frag; - QOpenGLShader vert; - QOpenGLShaderProgram program; }; #endif // INVERTEFFECT_H diff --git a/effects/video/solideffect.cpp b/effects/video/solideffect.cpp index d83f041f3..96fe19e43 100644 --- a/effects/video/solideffect.cpp +++ b/effects/video/solideffect.cpp @@ -15,7 +15,7 @@ #define SMPTE_STRIP_COUNT 3 #define SMPTE_LOWER_BARS 4 -SolidEffect::SolidEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SOLID_EFFECT), vert(QOpenGLShader::Vertex), frag(QOpenGLShader::Fragment) { +SolidEffect::SolidEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SOLID_EFFECT) { enable_opengl = true; solid_type = add_row("Type:")->add_field(EFFECT_FIELD_COMBO); @@ -34,22 +34,15 @@ SolidEffect::SolidEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_SOLID_EFF connect(solid_color_field, SIGNAL(changed()), this, SLOT(field_changed())); connect(opacity_field, SIGNAL(changed()), this, SLOT(field_changed())); - vert.compileSourceFile(":/shaders/common.vert"); - frag.compileSourceFile(":/shaders/solideffect.frag"); - program.addShader(&vert); - program.addShader(&frag); + vertPath = ":/shaders/common.vert"; + fragPath = ":/shaders/solideffect.frag"; } void SolidEffect::process_gl(double timecode, GLTextureCoords&) { solid_color_field->set_enabled(solid_type->get_combo_data(timecode) == SOLID_TYPE_COLOR); - program.bind(); - program.setUniformValue("solidColor", solid_color_field->get_color_value(timecode)); - program.setUniformValue("amount_val", (GLfloat) (opacity_field->get_double_value(timecode)*0.01)); -} - -void SolidEffect::clean_gl() { - program.release(); + glslProgram->setUniformValue("solidColor", solid_color_field->get_color_value(timecode)); + glslProgram->setUniformValue("amount_val", (GLfloat) (opacity_field->get_double_value(timecode)*0.01)); } void SolidEffect::process_image(long frame, uint8_t* data, int w, int h) { diff --git a/effects/video/solideffect.h b/effects/video/solideffect.h index fb37e4b7f..222cf26ce 100644 --- a/effects/video/solideffect.h +++ b/effects/video/solideffect.h @@ -11,12 +11,7 @@ public: EffectField* solid_color_field; EffectField* opacity_field; void process_gl(double timecode, GLTextureCoords& coords); - void clean_gl(); - void process_image(long p, uint8_t* data, int width, int height); -private: - QOpenGLShaderProgram program; - QOpenGLShader vert; - QOpenGLShader frag; + void process_image(long p, uint8_t* data, int width, int height); }; #endif // SOLIDEFFECT_H diff --git a/playback/cacher.cpp b/playback/cacher.cpp index df8962114..bef01ac21 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -385,6 +385,10 @@ void open_clip_worker(Clip* clip) { clip->audio_reset = true; } + for (int i=0;ieffects.size();i++) { + clip->effects.at(i)->open(); + } + clip->frame = av_frame_alloc(); clip->finished_opening = true; @@ -414,6 +418,10 @@ void cache_clip_worker(Clip* clip, long playhead, bool write_A, bool write_B, bo } void close_clip_worker(Clip* clip) { + for (int i=0;ieffects.size();i++) { + clip->effects.at(i)->close(); + } + // closes ffmpeg file handle and frees any memory used for caching MediaStream* ms = static_cast(clip->media)->get_stream_from_file_index(clip->track < 0, clip->media_stream); if (clip->track < 0) { diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 0822d4e0b..05def23ea 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -216,6 +216,7 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) { // EFFECT CODE START for (int j=0;jeffects.size();j++) { if (c->effects.at(j)->enable_opengl && c->effects.at(j)->is_enabled()) { + c->effects.at(j)->startEffect(); for (int k=0;keffects.at(j)->getIterations();k++) { c->effects.at(j)->process_gl(((double)(panel_timeline->playhead-c->timeline_in+c->clip_in)/(double)sequence->frame_rate), coords); composite_texture = draw_clip(c, composite_texture); @@ -240,7 +241,7 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) { for (int j=0;jeffects.size();j++) { if (c->effects.at(j)->enable_opengl && c->effects.at(j)->is_enabled()) { - c->effects.at(j)->clean_gl(); + c->effects.at(j)->endEffect(); } }