X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Foverlay%2Foverlay.C;h=8f8cdea5693999439027ac3badb3036f059d7ad2;hb=b2eb290b3f6e5c233393017aa152e67c76243130;hp=d3bdd92cf1d44db950710b387b992cd44203e2aa;hpb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/plugins/overlay/overlay.C b/cinelerra-5.1/plugins/overlay/overlay.C index d3bdd92c..8f8cdea5 100644 --- a/cinelerra-5.1/plugins/overlay/overlay.C +++ b/cinelerra-5.1/plugins/overlay/overlay.C @@ -22,12 +22,14 @@ #include "bcdisplayinfo.h" #include "clip.h" #include "bchash.h" +#include "edlsession.h" #include "filexml.h" #include "guicast.h" #include "keyframe.h" #include "language.h" #include "overlayframe.h" #include "pluginvclient.h" +#include "vpatchgui.h" #include "vframe.h" #include @@ -136,9 +138,7 @@ public: VFrame *temp; int current_layer; int output_layer; -// Inclusive layer numbers - int input_layer1; - int input_layer2; + int input_layer; }; OverlayConfig::OverlayConfig() @@ -150,33 +150,7 @@ OverlayConfig::OverlayConfig() const char* OverlayConfig::mode_to_text(int mode) { - switch(mode) { - case TRANSFER_NORMAL: return _("Normal"); - case TRANSFER_ADDITION: return _("Addition"); - case TRANSFER_SUBTRACT: return _("Subtract"); - case TRANSFER_MULTIPLY: return _("Multiply"); - case TRANSFER_DIVIDE: return _("Divide"); - case TRANSFER_REPLACE: return _("Replace"); - case TRANSFER_MAX: return _("Max"); - case TRANSFER_MIN: return _("Min"); - case TRANSFER_AVERAGE: return _("Average"); - case TRANSFER_DARKEN: return _("Darken"); - case TRANSFER_LIGHTEN: return _("Lighten"); - case TRANSFER_DST: return _("Dst"); - case TRANSFER_DST_ATOP: return _("DstAtop"); - case TRANSFER_DST_IN: return _("DstIn"); - case TRANSFER_DST_OUT: return _("DstOut"); - case TRANSFER_DST_OVER: return _("DstOver"); - case TRANSFER_SRC: return _("Src"); - case TRANSFER_SRC_ATOP: return _("SrcAtop"); - case TRANSFER_SRC_IN: return _("SrcIn"); - case TRANSFER_SRC_OUT: return _("SrcOut"); - case TRANSFER_SRC_OVER: return _("SrcOver"); - case TRANSFER_OR: return _("Or"); - case TRANSFER_XOR: return _("Xor"); - default: break; - } - return _("Normal"); + return VModePatch::mode_to_text(mode); } const char* OverlayConfig::direction_to_text(int direction) @@ -419,93 +393,44 @@ int Overlay::process_buffer(VFrame **frame, { load_configuration(); - - if(!temp) temp = new VFrame(0, - -1, - frame[0]->get_w(), - frame[0]->get_h(), - frame[0]->get_color_model(), - -1); - - if(!overlayer) - overlayer = new OverlayFrame(get_project_smp() + 1); - - int step; - VFrame *output; - - if(config.direction == OverlayConfig::BOTTOM_FIRST) - { - input_layer1 = get_total_buffers() - 1; - input_layer2 = -1; - step = -1; - } - else - { - input_layer1 = 0; - input_layer2 = get_total_buffers(); - step = 1; - } - - if(config.output_layer == OverlayConfig::TOP) - { - output_layer = 0; - } - else - { - output_layer = get_total_buffers() - 1; - } - - - -// Direct copy the first layer - output = frame[output_layer]; - read_frame(output, - input_layer1, - start_position, - frame_rate, - get_use_opengl()); - - if(get_total_buffers() == 1) return 0; - - - - current_layer = input_layer1; - if(get_use_opengl()) - run_opengl(); - - for(int i = input_layer1 + step; i != input_layer2; i += step) - { - read_frame(temp, - i, - start_position, - frame_rate, - get_use_opengl()); - -// Call the opengl handler once for each layer - if(get_use_opengl()) - { - current_layer = i; - run_opengl(); - } - else - { - overlayer->overlay(output, - temp, - 0, - 0, - output->get_w(), - output->get_h(), - 0, - 0, - output->get_w(), - output->get_h(), - 1, - config.mode, - NEAREST_NEIGHBOR); + EDLSession* session = get_edlsession(); + int interpolation_type = session ? session->interpolation_type : NEAREST_NEIGHBOR; + + int step = config.direction == OverlayConfig::BOTTOM_FIRST ? -1 : 1; + int layers = get_total_buffers(); + input_layer = config.direction == OverlayConfig::BOTTOM_FIRST ? layers-1 : 0; + output_layer = config.output_layer == OverlayConfig::TOP ? 0 : layers-1; + VFrame *output = frame[output_layer]; + + current_layer = input_layer; + read_frame(output, current_layer, // Direct copy the first layer + start_position, frame_rate, get_use_opengl()); + + if( --layers > 0 ) { // need 2 layers to do overlay + if( !temp ) + temp = new VFrame(frame[0]->get_w(), frame[0]->get_h(), + frame[0]->get_color_model(), 0); + + while( --layers >= 0 ) { + current_layer += step; + read_frame(temp, current_layer, + start_position, frame_rate, get_use_opengl()); + + if(get_use_opengl()) { + run_opengl(); + continue; + } + + if(!overlayer) + overlayer = new OverlayFrame(get_project_smp() + 1); + + overlayer->overlay(output, temp, + 0, 0, output->get_w(), output->get_h(), + 0, 0, output->get_w(), output->get_h(), + 1, config.mode, interpolation_type); } } - return 0; } @@ -519,170 +444,195 @@ int Overlay::handle_opengl() "uniform vec3 chroma_offset;\n" "void main()\n" "{\n" - " vec4 result_color;\n" " vec4 dst_color = texture2D(dst_tex, gl_FragCoord.xy / dst_tex_dimensions);\n" " vec4 src_color = texture2D(src_tex, gl_TexCoord[0].st);\n" " src_color.rgb -= chroma_offset;\n" " dst_color.rgb -= chroma_offset;\n"; static const char *put_pixels_frag = - " result_color.rgb += chroma_offset;\n" - " result_color.rgb = mix(dst_color.rgb, result_color.rgb, src_color.a);\n" - " result_color.a = max(src_color.a, dst_color.a);\n" - " gl_FragColor = result_color;\n" + " result.rgb += chroma_offset;\n" + " gl_FragColor = result;\n" "}\n"; - static const char *blend_add_frag = - " result_color.rgb = dst_color.rgb + src_color.rgb;\n"; - - static const char *blend_max_frag = - " result_color.r = max(abs(dst_color.r, src_color.r);\n" - " result_color.g = max(abs(dst_color.g, src_color.g);\n" - " result_color.b = max(abs(dst_color.b, src_color.b);\n"; - - static const char *blend_min_frag = - " result_color.r = min(abs(dst_color.r, src_color.r);\n" - " result_color.g = min(abs(dst_color.g, src_color.g);\n" - " result_color.b = min(abs(dst_color.b, src_color.b);\n"; - - static const char *blend_subtract_frag = - " result_color.rgb = dst_color.rgb - src_color.rgb;\n"; - - - static const char *blend_multiply_frag = - " result_color.rgb = dst_color.rgb * src_color.rgb;\n"; - - static const char *blend_divide_frag = - " result_color.rgb = dst_color.rgb / src_color.rgb;\n" - " if(src_color.r == 0.0) result_color.r = 1.0;\n" - " if(src_color.g == 0.0) result_color.g = 1.0;\n" - " if(src_color.b == 0.0) result_color.b = 1.0;\n"; - +#define QQ(q)#q +#define SS(s)QQ(s) + +#define GL_STD_FRAG(FN) static const char *blend_##FN##_frag = \ + " vec4 result;\n" \ + " result.rgb = " SS(COLOR_##FN(1.0, src_color.rgb, src_color.a, dst_color.rgb, dst_color.a)) ";\n" \ + " result.a = " SS(ALPHA_##FN(1.0, src_color.a, dst_color.a))";\n" \ + +#define GL_VEC_FRAG(FN) static const char *blend_##FN##_frag = \ + " vec4 result;\n" \ + " result.r = " SS(COLOR_##FN(1.0, src_color.r, src_color.a, dst_color.r, dst_color.a)) ";\n" \ + " result.g = " SS(COLOR_##FN(1.0, src_color.g, src_color.a, dst_color.g, dst_color.a)) ";\n" \ + " result.b = " SS(COLOR_##FN(1.0, src_color.b, src_color.a, dst_color.b, dst_color.a)) ";\n" \ + " result.a = " SS(ALPHA_##FN(1.0, src_color.a, dst_color.a)) ";\n" \ + " result = clamp(result, 0.0, 1.0);\n" \ + +#undef mabs +#define mabs abs +#undef mmin +#define mmin min +#undef mmax +#define mmax max + +#undef ZERO +#define ZERO 0.0 +#undef ONE +#define ONE 1.0 +#undef TWO +#define TWO 2.0 + +static const char *blend_NORMAL_frag = + " vec4 result = mix(src_color, src_color, src_color.a);\n"; + +static const char *blend_ADDITION_frag = + " vec4 result = dst_color + src_color;\n" + " result = clamp(result, 0.0, 1.0);\n"; + +static const char *blend_SUBTRACT_frag = + " vec4 result = dst_color - src_color;\n" + " result = clamp(result, 0.0, 1.0);\n"; + +static const char *blend_REPLACE_frag = + " vec4 result = src_color;\n"; + +GL_STD_FRAG(MULTIPLY); +GL_VEC_FRAG(DIVIDE); +GL_VEC_FRAG(MAX); +GL_VEC_FRAG(MIN); +GL_VEC_FRAG(DARKEN); +GL_VEC_FRAG(LIGHTEN); +GL_STD_FRAG(DST); +GL_STD_FRAG(DST_ATOP); +GL_STD_FRAG(DST_IN); +GL_STD_FRAG(DST_OUT); +GL_STD_FRAG(DST_OVER); +GL_STD_FRAG(SRC); +GL_STD_FRAG(SRC_ATOP); +GL_STD_FRAG(SRC_IN); +GL_STD_FRAG(SRC_OUT); +GL_STD_FRAG(SRC_OVER); +GL_STD_FRAG(AND); +GL_STD_FRAG(OR); +GL_STD_FRAG(XOR); +GL_VEC_FRAG(OVERLAY); +GL_STD_FRAG(SCREEN); +GL_VEC_FRAG(BURN); +GL_VEC_FRAG(DODGE); +GL_VEC_FRAG(HARDLIGHT); +GL_VEC_FRAG(SOFTLIGHT); +GL_VEC_FRAG(DIFFERENCE); + +static const char * const overlay_shaders[TRANSFER_TYPES] = { + blend_NORMAL_frag, // TRANSFER_NORMAL + blend_ADDITION_frag, // TRANSFER_ADDITION + blend_SUBTRACT_frag, // TRANSFER_SUBTRACT + blend_MULTIPLY_frag, // TRANSFER_MULTIPLY + blend_DIVIDE_frag, // TRANSFER_DIVIDE + blend_REPLACE_frag, // TRANSFER_REPLACE + blend_MAX_frag, // TRANSFER_MAX + blend_MIN_frag, // TRANSFER_MIN + blend_DARKEN_frag, // TRANSFER_DARKEN + blend_LIGHTEN_frag, // TRANSFER_LIGHTEN + blend_DST_frag, // TRANSFER_DST + blend_DST_ATOP_frag, // TRANSFER_DST_ATOP + blend_DST_IN_frag, // TRANSFER_DST_IN + blend_DST_OUT_frag, // TRANSFER_DST_OUT + blend_DST_OVER_frag, // TRANSFER_DST_OVER + blend_SRC_frag, // TRANSFER_SRC + blend_SRC_ATOP_frag, // TRANSFER_SRC_ATOP + blend_SRC_IN_frag, // TRANSFER_SRC_IN + blend_SRC_OUT_frag, // TRANSFER_SRC_OUT + blend_SRC_OVER_frag, // TRANSFER_SRC_OVER + blend_AND_frag, // TRANSFER_AND + blend_OR_frag, // TRANSFER_OR + blend_XOR_frag, // TRANSFER_XOR + blend_OVERLAY_frag, // TRANSFER_OVERLAY + blend_SCREEN_frag, // TRANSFER_SCREEN + blend_BURN_frag, // TRANSFER_BURN + blend_DODGE_frag, // TRANSFER_DODGE + blend_HARDLIGHT_frag, // TRANSFER_HARDLIGHT + blend_SOFTLIGHT_frag, // TRANSFER_SOFTLIGHT + blend_DIFFERENCE_frag, // TRANSFER_DIFFERENCE +}; - VFrame *src = temp; + glDisable(GL_BLEND); VFrame *dst = get_output(output_layer); + VFrame *src = temp; - dst->enable_opengl(); - dst->init_screen(); - - const char *shader_stack[] = { 0, 0, 0 }; - int current_shader = 0; - - - - + switch( config.mode ) { + case TRANSFER_REPLACE: + case TRANSFER_SRC: // Direct copy layer - if(config.mode == TRANSFER_REPLACE) - { - src->to_texture(); - src->bind_texture(0); - dst->enable_opengl(); + src->to_texture(); + dst->enable_opengl(); dst->init_screen(); - -// Multiply alpha - glDisable(GL_BLEND); src->draw_texture(); - } - else - if(config.mode == TRANSFER_NORMAL) - { - dst->enable_opengl(); - dst->init_screen(); - + break; + case TRANSFER_NORMAL: // Move destination to screen - if(dst->get_opengl_state() != VFrame::SCREEN) - { + if( dst->get_opengl_state() != VFrame::SCREEN ) { dst->to_texture(); - dst->bind_texture(0); + dst->enable_opengl(); + dst->init_screen(); dst->draw_texture(); } - - src->to_texture(); - src->bind_texture(0); - dst->enable_opengl(); + src->to_texture(); + dst->enable_opengl(); dst->init_screen(); - glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); src->draw_texture(); - } - else - { -// Read destination back to texture + break; + default: + src->to_texture(); dst->to_texture(); - - src->enable_opengl(); - src->init_screen(); - src->to_texture(); - - dst->enable_opengl(); + dst->enable_opengl(); dst->init_screen(); - src->bind_texture(0); - dst->bind_texture(1); + src->bind_texture(0); + dst->bind_texture(1); + const char *shader_stack[16]; + memset(shader_stack,0, sizeof(shader_stack)); + int current_shader = 0; shader_stack[current_shader++] = get_pixels_frag; - - switch(config.mode) - { - case TRANSFER_ADDITION: - shader_stack[current_shader++] = blend_add_frag; - break; - case TRANSFER_SUBTRACT: - shader_stack[current_shader++] = blend_subtract_frag; - break; - case TRANSFER_MULTIPLY: - shader_stack[current_shader++] = blend_multiply_frag; - break; - case TRANSFER_DIVIDE: - shader_stack[current_shader++] = blend_divide_frag; - break; - case TRANSFER_MAX: - shader_stack[current_shader++] = blend_max_frag; - break; - case TRANSFER_MIN: - shader_stack[current_shader++] = blend_min_frag; - break; - } - + shader_stack[current_shader++] = overlay_shaders[config.mode]; shader_stack[current_shader++] = put_pixels_frag; - - unsigned int shader_id = 0; - shader_id = VFrame::make_shader(0, - shader_stack[0], - shader_stack[1], - shader_stack[2], - 0); - - glUseProgram(shader_id); - glUniform1i(glGetUniformLocation(shader_id, "src_tex"), 0); - glUniform1i(glGetUniformLocation(shader_id, "dst_tex"), 1); - if(BC_CModels::is_yuv(dst->get_color_model())) - glUniform3f(glGetUniformLocation(shader_id, "chroma_offset"), 0.0, 0.5, 0.5); - else - glUniform3f(glGetUniformLocation(shader_id, "chroma_offset"), 0.0, 0.0, 0.0); - glUniform2f(glGetUniformLocation(shader_id, "dst_tex_dimensions"), - (float)dst->get_texture_w(), - (float)dst->get_texture_h()); - - glDisable(GL_BLEND); + shader_stack[current_shader] = 0; + unsigned int shader = VFrame::make_shader(shader_stack); + if( shader > 0 ) { + glUseProgram(shader); + glUniform1i(glGetUniformLocation(shader, "src_tex"), 0); + glUniform1i(glGetUniformLocation(shader, "dst_tex"), 1); + glUniform2f(glGetUniformLocation(shader, "dst_tex_dimensions"), + (float)dst->get_texture_w(), (float)dst->get_texture_h()); + float chroma_offset = BC_CModels::is_yuv(dst->get_color_model()) ? 0.5 : 0.0; + glUniform3f(glGetUniformLocation(shader, "chroma_offset"), + 0.0, chroma_offset, chroma_offset); + } src->draw_texture(); glUseProgram(0); + + glActiveTexture(GL_TEXTURE1); + glDisable(GL_TEXTURE_2D); + break; } - glDisable(GL_BLEND); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); - dst->set_opengl_state(VFrame::SCREEN); +// get the data before something else uses the screen + dst->screen_to_ram(); #endif return 0; } -const char* Overlay::plugin_title() { return _("Overlay"); } +const char* Overlay::plugin_title() { return N_("Overlay"); } int Overlay::is_realtime() { return 1; } int Overlay::is_multichannel() { return 1; } int Overlay::is_synthesis() { return 1; } @@ -707,7 +657,7 @@ void Overlay::save_data(KeyFrame *keyframe) FileXML output; // cause data to be stored directly in text - output.set_shared_output(keyframe->get_data(), MESSAGESIZE); + output.set_shared_output(keyframe->xbuf); output.tag.set_title("OVERLAY"); output.tag.set_property("MODE", config.mode); output.tag.set_property("DIRECTION", config.direction); @@ -722,7 +672,7 @@ void Overlay::read_data(KeyFrame *keyframe) { FileXML input; - input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + input.set_shared_input(keyframe->xbuf); while(!input.read_tag()) {