X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fplayback3d.C;h=2ca2a4c68e4d43f35f03595d76f23e8a6483d1d4;hp=f733105ff231bb18b1b648c69b860f3fb7895701;hb=a19a685a46ddc630010788707d9e5b9d2342af46;hpb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd diff --git a/cinelerra-5.1/cinelerra/playback3d.C b/cinelerra-5.1/cinelerra/playback3d.C index f733105f..2ca2a4c6 100644 --- a/cinelerra-5.1/cinelerra/playback3d.C +++ b/cinelerra-5.1/cinelerra/playback3d.C @@ -21,18 +21,23 @@ #define GL_GLEXT_PROTOTYPES +#include "bccolors.h" #include "bcsignals.h" #include "bcwindowbase.h" #include "canvas.h" #include "clip.h" #include "condition.h" +#include "edl.h" #include "maskautos.h" #include "maskauto.h" #include "mutex.h" +#include "mwindow.h" #include "overlayframe.inc" +#include "overlayframe.h" #include "playback3d.h" #include "pluginclient.h" #include "pluginvclient.h" +#include "edlsession.h" #include "transportque.inc" #include "vframe.h" @@ -46,6 +51,8 @@ #include #include +#define QQ(q)#q +#define SS(s)QQ(s) // Shaders @@ -53,16 +60,15 @@ // Can't hard code sampler2D +#ifdef HAVE_GL static const char *yuv_to_rgb_frag = "uniform sampler2D tex;\n" + "uniform mat3 yuv_to_rgb_matrix;\n" + "uniform float yminf;\n" "void main()\n" "{\n" " vec4 yuva = texture2D(tex, gl_TexCoord[0].st);\n" - " yuva.rgb -= vec3(0, 0.5, 0.5);\n" - " const mat3 yuv_to_rgb_matrix = mat3(\n" - " 1, 1, 1, \n" - " 0, -0.34414, 1.77200, \n" - " 1.40200, -0.71414, 0);\n" + " yuva.rgb -= vec3(yminf, 0.5, 0.5);\n" " gl_FragColor = vec4(yuv_to_rgb_matrix * yuva.rgb, yuva.a);\n" "}\n"; @@ -82,14 +88,12 @@ static const char *yuva_to_yuv_frag = static const char *yuva_to_rgb_frag = "uniform sampler2D tex;\n" + "uniform mat3 yuv_to_rgb_matrix;\n" + "uniform float yminf;\n" "void main()\n" "{\n" " vec4 yuva = texture2D(tex, gl_TexCoord[0].st);\n" - " yuva.rgb -= vec3(0, 0.5, 0.5);\n" - " const mat3 yuv_to_rgb_matrix = mat3(\n" - " 1, 1, 1, \n" - " 0, -0.34414, 1.77200, \n" - " 1.40200, -0.71414, 0);\n" + " yuva.rgb -= vec3(yminf, 0.5, 0.5);\n" " yuva.rgb = yuv_to_rgb_matrix * yuva.rgb;\n" " yuva.rgb *= yuva.a;\n" " yuva.a = 1.0;\n" @@ -98,15 +102,13 @@ static const char *yuva_to_rgb_frag = static const char *rgb_to_yuv_frag = "uniform sampler2D tex;\n" + "uniform mat3 rgb_to_yuv_matrix;\n" + "uniform float yminf;\n" "void main()\n" "{\n" " vec4 rgba = texture2D(tex, gl_TexCoord[0].st);\n" - " const mat3 rgb_to_yuv_matrix = mat3(\n" - " 0.29900, -0.16874, 0.50000, \n" - " 0.58700, -0.33126, -0.41869, \n" - " 0.11400, 0.50000, -0.08131);\n" " rgba.rgb = rgb_to_yuv_matrix * rgba.rgb;\n" - " rgba.rgb += vec3(0, 0.5, 0.5);\n" + " rgba.rgb += vec3(yminf, 0.5, 0.5);\n" " gl_FragColor = rgba;\n" "}\n"; @@ -123,322 +125,132 @@ static const char *rgba_to_rgb_frag = static const char *rgba_to_yuv_frag = "uniform sampler2D tex;\n" + "uniform mat3 rgb_to_yuv_matrix;\n" + "uniform float yminf;\n" "void main()\n" "{\n" " vec4 rgba = texture2D(tex, gl_TexCoord[0].st);\n" - " const mat3 rgb_to_yuv_matrix = mat3(\n" - " 0.29900, -0.16874, 0.50000, \n" - " 0.58700, -0.33126, -0.41869, \n" - " 0.11400, 0.50000, -0.08131);\n" " rgba.rgb *= rgba.a;\n" " rgba.a = 1.0;\n" " rgba.rgb = rgb_to_yuv_matrix * rgba.rgb;\n" - " rgba.rgb += vec3(0, 0.5, 0.5);\n" + " rgba.rgb += vec3(yminf, 0.5, 0.5);\n" " gl_FragColor = rgba;\n" "}\n"; -static const char *rgba_to_rgb_flatten = - "void main() {\n" - " gl_FragColor.rgb *= gl_FragColor.a;\n" - " gl_FragColor.a = 1.0;\n" - "}\n"; +//static const char *rgba_to_rgb_flatten = +// "void main() {\n" +// " gl_FragColor.rgb *= gl_FragColor.a;\n" +// " gl_FragColor.a = 1.0;\n" +// "}\n"; + +#define GL_STD_BLEND(FN) \ +static const char *blend_##FN##_frag = \ + "uniform sampler2D tex2;\n" \ + "uniform vec2 tex2_dimensions;\n" \ + "uniform float alpha;\n" \ + "void main() {\n" \ + " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" \ + " vec4 result;\n" \ + " result.rgb = " SS(COLOR_##FN(1.0, gl_FragColor.rgb, gl_FragColor.a, canvas.rgb, canvas.a)) ";\n" \ + " result.a = " SS(ALPHA_##FN(1.0, gl_FragColor.a, canvas.a)) ";\n" \ + " gl_FragColor = mix(canvas, result, alpha);\n" \ + "}\n" + +#define GL_VEC_BLEND(FN) \ +static const char *blend_##FN##_frag = \ + "uniform sampler2D tex2;\n" \ + "uniform vec2 tex2_dimensions;\n" \ + "uniform float alpha;\n" \ + "void main() {\n" \ + " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" \ + " vec4 result;\n" \ + " result.r = " SS(COLOR_##FN(1.0, gl_FragColor.r, gl_FragColor.a, canvas.r, canvas.a)) ";\n" \ + " result.g = " SS(COLOR_##FN(1.0, gl_FragColor.g, gl_FragColor.a, canvas.g, canvas.a)) ";\n" \ + " result.b = " SS(COLOR_##FN(1.0, gl_FragColor.b, gl_FragColor.a, canvas.b, canvas.a)) ";\n" \ + " result.a = " SS(ALPHA_##FN(1.0, gl_FragColor.a, canvas.a)) ";\n" \ + " result = clamp(result, 0.0, 1.0);\n" \ + " gl_FragColor = mix(canvas, result, alpha);\n" \ + "}\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 // NORMAL -static const char *blend_normal_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas * (1.0 - gl_FragColor.a) + gl_FragColor * gl_FragColor.a;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// ADDITION -static const char *blend_add_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas + gl_FragColor;\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SUBTRACT -static const char *blend_subtract_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor - canvas;\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// MULTIPLY -static const char *blend_multiply_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas * gl_FragColor;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DIVIDE -static const char *blend_divide_frag = +static const char *blend_NORMAL_frag = "uniform sampler2D tex2;\n" "uniform vec2 tex2_dimensions;\n" "uniform float alpha;\n" "void main() {\n" - " gl_FragColor.a *= alpha;\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor / canvas;\n" - " if(!canvas.r) result.r = 1.0;\n" - " if(!canvas.g) result.g = 1.0;\n" - " if(!canvas.b) result.b = 1.0;\n" - " if(!canvas.a) result.a = 1.0;\n" - " result = clamp(result, 0.0, 1.0);\n" + " vec4 result = mix(canvas, gl_FragColor, gl_FragColor.a);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; // REPLACE -static const char *blend_replace_frag = - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - "}\n"; - -// MAX -static const char *blend_max_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = max(canvas, gl_FragColor);\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// MIN -static const char *blend_min_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = min(canvas, gl_FragColor);\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// AVERAGE -static const char *blend_average_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = (canvas + gl_FragColor) * 0.5;\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DARKEN -static const char *blend_darken_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(canvas.rgb * (1.0 - gl_FragColor.a) +" - " gl_FragColor.rgb * (1.0 - canvas.a) +" - " min(canvas.rgb, gl_FragColor.rgb), " - " canvas.a + gl_FragColor.a - canvas.a * gl_FragColor.a);\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// LIGHTEN -static const char *blend_lighten_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(canvas.rgb * (1.0 - gl_FragColor.a) +" - " gl_FragColor.rgb * (1.0 - canvas.a) +" - " max(canvas.rgb, gl_FragColor.rgb), " - " canvas.a + gl_FragColor.a - canvas.a * gl_FragColor.a);\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DST -static const char *blend_dst_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" -// " gl_FragColor.a *= alpha;\n" -// " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" -// " vec4 result = canvas;\n" -// " gl_FragColor = mix(result, canvas, alpha);\n" - " gl_FragColor = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - "}\n"; - -// DST_ATOP -static const char *blend_dst_atop_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(canvas.rgb * gl_FragColor.a + " - "(1.0 - canvas.a) * gl_FragColor.rgb, gl_FragColor.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DST_IN -static const char *blend_dst_in_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas * gl_FragColor.a;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DST_OUT -static const char *blend_dst_out_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas * (1.0 - gl_FragColor.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DST_OVER -static const char *blend_dst_over_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(canvas.rgb + (1.0 - canvas.a) * gl_FragColor.rgb, " - " gl_FragColor.a + canvas.a - gl_FragColor.a * canvas.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC -static const char *blend_src_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC_ATOP -static const char *blend_src_atop_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(gl_FragColor.rgb * canvas.a + " - "canvas.rgb * (1.0 - gl_FragColor.a), canvas.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC_IN -static const char *blend_src_in_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor * canvas.a;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC_OUT -static const char *blend_src_out_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" +static const char *blend_REPLACE_frag = "uniform float alpha;\n" "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor * (1.0 - canvas.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; -// SRC_OVER -static const char *blend_src_over_frag = +// ADDITION +static const char *blend_ADDITION_frag = "uniform sampler2D tex2;\n" "uniform vec2 tex2_dimensions;\n" "uniform float alpha;\n" "void main() {\n" - " gl_FragColor.a *= alpha;\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(gl_FragColor.rgb + (1.0 - gl_FragColor.a) * canvas.rgb, " - "gl_FragColor.a + canvas.a - gl_FragColor.a * canvas.a);\n" + " vec4 result = clamp(gl_FragColor + canvas, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; -// OR -static const char *blend_or_frag = +// SUBTRACT +static const char *blend_SUBTRACT_frag = "uniform sampler2D tex2;\n" "uniform vec2 tex2_dimensions;\n" "uniform float alpha;\n" "void main() {\n" - " gl_FragColor.a *= alpha;\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas + gl_FragColor - canvas * gl_FragColor;\n" - " result = clamp(result, 0.0, 1.0);\n" + " vec4 result = clamp(gl_FragColor - canvas, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; -// XOR -static const char *blend_xor_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " gl_FragColor.a *= alpha;\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(gl_FragColor.rgb * (1.0 - canvas.a) + " - "(1.0 - gl_FragColor.a) * canvas.rgb, " - "gl_FragColor.a + canvas.a - 2.0 * gl_FragColor.a * canvas.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; +GL_STD_BLEND(MULTIPLY); +GL_VEC_BLEND(DIVIDE); +GL_VEC_BLEND(MAX); +GL_VEC_BLEND(MIN); +GL_VEC_BLEND(DARKEN); +GL_VEC_BLEND(LIGHTEN); +GL_STD_BLEND(DST); +GL_STD_BLEND(DST_ATOP); +GL_STD_BLEND(DST_IN); +GL_STD_BLEND(DST_OUT); +GL_STD_BLEND(DST_OVER); +GL_STD_BLEND(SRC); +GL_STD_BLEND(SRC_ATOP); +GL_STD_BLEND(SRC_IN); +GL_STD_BLEND(SRC_OUT); +GL_STD_BLEND(SRC_OVER); +GL_STD_BLEND(AND); +GL_STD_BLEND(OR); +GL_STD_BLEND(XOR); +GL_VEC_BLEND(OVERLAY); +GL_STD_BLEND(SCREEN); +GL_VEC_BLEND(BURN); +GL_VEC_BLEND(DODGE); +GL_VEC_BLEND(HARDLIGHT); +GL_VEC_BLEND(SOFTLIGHT); +GL_VEC_BLEND(DIFFERENCE); static const char *read_texture_frag = "uniform sampler2D tex;\n" @@ -504,11 +316,7 @@ static const char *fade_yuv_frag = " gl_FragColor.gb += vec2(0.5, 0.5);\n" "}\n"; - - - - - +#endif Playback3DCommand::Playback3DCommand() @@ -693,12 +501,23 @@ void Playback3D::copy_from_sync(Playback3DCommand *command) else // Copy to RAM { - command->input->enable_opengl(); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, - command->frame->get_rows()[0]); - command->frame->flip_vert(); - command->frame->set_opengl_state(VFrame::RAM); + command->input->to_texture(); + command->input->bind_texture(0); + command->frame->enable_opengl(); + command->frame->init_screen(); + unsigned int shader = BC_CModels::is_yuv(command->input->get_color_model()) ? + VFrame::make_shader(0, yuv_to_rgb_frag, 0) : 0; + if( shader > 0 ) { + glUseProgram(shader); + int variable = glGetUniformLocation(shader, "tex"); + glUniform1i(variable, 0); + BC_GL_YUV_TO_RGB(shader); + } + else + glUseProgram(0); + command->input->draw_texture(1); + command->frame->screen_to_ram(); + glUseProgram(0); } } else @@ -762,7 +581,7 @@ void Playback3D::copy_from_sync(Playback3DCommand *command) // command->frame->get_h(), // BC_RGB888, // -1); -// command->frame->to_ram(); +// command->frame->screen_to_ram(); // // window->clear_box(0, // 0, @@ -829,27 +648,31 @@ void Playback3D::write_buffer_sync(Playback3DCommand *command) // Make sure OpenGL is enabled first. window->enable_opengl(); - //printf("Playback3D::write_buffer_sync 1 %d\n", window->get_id()); - switch(command->frame->get_opengl_state()) - { + int flip_y = 0, frame_state = command->frame->get_opengl_state(); + switch( frame_state ) { // Upload texture and composite to screen case VFrame::RAM: + flip_y = 1; + case VFrame::SCREEN: command->frame->to_texture(); - draw_output(command); - break; + window->enable_opengl(); // Composite texture to screen and swap buffer case VFrame::TEXTURE: - draw_output(command); - break; - case VFrame::SCREEN: -// swap buffers only - window->flip_opengl(); + if( !flip_y ) { + int fh1 = command->frame->get_h()-1; + float in_y1 = fh1 - command->in_y1; + float in_y2 = fh1 - command->in_y2; + command->in_y1 = in_y2; + command->in_y2 = in_y1; + } + draw_output(command, flip_y); break; default: printf("Playback3D::write_buffer_sync unknown state\n"); break; } + command->frame->set_opengl_state(frame_state); window->unlock_window(); } @@ -858,7 +681,7 @@ void Playback3D::write_buffer_sync(Playback3DCommand *command) -void Playback3D::draw_output(Playback3DCommand *command) +void Playback3D::draw_output(Playback3DCommand *command, int flip_y) { #ifdef HAVE_GL int texture_id = command->frame->get_texture_id(); @@ -878,54 +701,42 @@ void Playback3D::draw_output(Playback3DCommand *command) canvas_w = window->get_w(); canvas_h = window->get_h(); VFrame::init_screen(canvas_w, canvas_h); + int color_model = command->frame->get_color_model(); + int is_yuv = BC_CModels::is_yuv(color_model); if(!command->is_cleared) { // If we get here, the virtual console was not used. - init_frame(command); + init_frame(command, 0); } // Texture // Undo any previous shader settings command->frame->bind_texture(0); - - - // Convert colormodel - unsigned int frag_shader = 0; - switch(command->frame->get_color_model()) - { - case BC_YUV888: - case BC_YUVA8888: - frag_shader = VFrame::make_shader(0, - yuv_to_rgb_frag, - 0); - break; - } - - - if(frag_shader > 0) - { - glUseProgram(frag_shader); - int variable = glGetUniformLocation(frag_shader, "tex"); + unsigned int shader = is_yuv ? VFrame::make_shader(0, yuv_to_rgb_frag, 0) : 0; + if( shader > 0 ) { + glUseProgram(shader); // Set texture unit of the texture + int variable = glGetUniformLocation(shader, "tex"); glUniform1i(variable, 0); + BC_GL_YUV_TO_RGB(shader); } - if(BC_CModels::components(command->frame->get_color_model()) == 4) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } +// if(BC_CModels::components(color_model) == 4) +// { +// glEnable(GL_BLEND); +// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// } command->frame->draw_texture( command->in_x1, command->in_y1, command->in_x2, command->in_y2, command->out_x1, command->out_y1, command->out_x2, command->out_y2, - 1); + flip_y); -// printf("Playback3D::draw_output 2 %f,%f %f,%f -> %f,%f %f,%f\n", +//printf("Playback3D::draw_output 2 %f,%f %f,%f -> %f,%f %f,%f\n", // command->in_x1, // command->in_y1, // command->in_x2, @@ -944,13 +755,11 @@ void Playback3D::draw_output(Playback3DCommand *command) } -void Playback3D::init_frame(Playback3DCommand *command) +void Playback3D::init_frame(Playback3DCommand *command, int is_yuv) { #ifdef HAVE_GL - canvas_w = command->canvas->get_canvas()->get_w(); - canvas_h = command->canvas->get_canvas()->get_h(); - - glClearColor(0.0, 0.0, 0.0, 0.0); + float gbuv = is_yuv ? 0.5 : 0.0; + glClearColor(0.0, gbuv, gbuv, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #endif } @@ -973,15 +782,17 @@ void Playback3D::clear_output_sync(Playback3DCommand *command) command->canvas->get_canvas()->lock_window("Playback3D::clear_output_sync"); // If we get here, the virtual console is being used. command->canvas->get_canvas()->enable_opengl(); + int is_yuv = 0; // Using pbuffer for refresh frame. if(command->frame) { command->frame->enable_opengl(); + int color_model = command->canvas->mwindow->edl->session->color_model; + is_yuv = BC_CModels::is_yuv(color_model); } - - init_frame(command); + init_frame(command, is_yuv); command->canvas->get_canvas()->unlock_window(); } command->canvas->unlock_canvas(); @@ -1075,6 +886,7 @@ void Playback3D::do_camera_sync(Playback3DCommand *command) command->frame->set_opengl_state(VFrame::SCREEN); + command->frame->screen_to_ram(); command->canvas->get_canvas()->unlock_window(); } command->canvas->unlock_canvas(); @@ -1112,29 +924,36 @@ void Playback3D::overlay_sync(Playback3DCommand *command) // To do these operations, we need to copy the input buffer to a texture // and blend 2 textures in a shader static const char * const overlay_shaders[TRANSFER_TYPES] = { - blend_normal_frag, // TRANSFER_NORMAL - blend_add_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_average_frag, // TRANSFER_AVERAGE - 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_or_frag, // TRANSFER_OR - blend_xor_frag // TRANSFER_XOR + 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 }; command->canvas->lock_canvas("Playback3D::overlay_sync"); @@ -1148,22 +967,9 @@ void Playback3D::overlay_sync(Playback3DCommand *command) glColor4f(1, 1, 1, 1); glDisable(GL_BLEND); - if(command->frame) { -// Render to PBuffer - command->frame->enable_opengl(); - command->frame->set_opengl_state(VFrame::SCREEN); - canvas_w = command->frame->get_w(); - canvas_h = command->frame->get_h(); - } - else { -// Render to canvas - canvas_w = window->get_w(); - canvas_h = window->get_h(); - } - //printf("Playback3D::overlay_sync 1 %d\n", command->input->get_opengl_state()); - switch(command->input->get_opengl_state()) { + switch( command->input->get_opengl_state() ) { // Upload texture and composite to screen case VFrame::RAM: command->input->to_texture(); @@ -1175,19 +981,30 @@ void Playback3D::overlay_sync(Playback3DCommand *command) case VFrame::SCREEN: command->input->enable_opengl(); command->input->screen_to_texture(); - if(command->frame) - command->frame->enable_opengl(); - else - window->enable_opengl(); break; default: printf("Playback3D::overlay_sync unknown state\n"); break; } + if(command->frame) { +// Render to PBuffer + command->frame->enable_opengl(); + command->frame->set_opengl_state(VFrame::SCREEN); + canvas_w = command->frame->get_w(); + canvas_h = command->frame->get_h(); + } + else { +// Render to canvas + window->enable_opengl(); + canvas_w = window->get_w(); + canvas_h = window->get_h(); + } + - const char *shader_stack[4] = { 0, 0, 0, 0, }; - int total_shaders = 0; + const char *shader_stack[16]; + memset(shader_stack,0, sizeof(shader_stack)); + int total_shaders = 0, need_matrix = 0; VFrame::init_screen(canvas_w, canvas_h); @@ -1196,14 +1013,11 @@ void Playback3D::overlay_sync(Playback3DCommand *command) // Convert colormodel to RGB if not nested. // The color model setting in the output frame is ignored. - if( command->is_nested <= 0 ) { // not nested - switch(command->input->get_color_model()) { - case BC_YUV888: - case BC_YUVA8888: - shader_stack[total_shaders++] = yuv_to_rgb_frag; - break; - } - } +// if( command->is_nested <= 0 && // not nested +// BC_CModels::is_yuv(command->input->get_color_model()) ) { +// need_matrix = 1; +// shader_stack[total_shaders++] = yuv_to_rgb_frag; +// } // get the shaders #define add_shader(s) \ @@ -1223,36 +1037,34 @@ void Playback3D::overlay_sync(Playback3DCommand *command) } // if to flatten alpha - if( command->is_nested < 0 ) { - switch(command->input->get_color_model()) { -// yuv has already been converted to rgb - case BC_YUVA8888: - case BC_RGBA_FLOAT: - case BC_RGBA8888: - add_shader(rgba_to_rgb_flatten); - break; - } - } +// if( command->is_nested < 0 ) { +// switch(command->input->get_color_model()) { +//// yuv has already been converted to rgb +// case BC_YUVA8888: +// case BC_RGBA_FLOAT: +// case BC_RGBA8888: +// add_shader(rgba_to_rgb_flatten); +// break; +// } +// } // run the shaders - unsigned int frag_shader = 0; - if(shader_stack[0]) { - frag_shader = VFrame::make_shader(0, - shader_stack[0], shader_stack[1], - shader_stack[2], shader_stack[3], 0); - - glUseProgram(frag_shader); - + add_shader(0); + unsigned int shader = !shader_stack[0] ? 0 : + VFrame::make_shader(shader_stack); + if( shader > 0 ) { + glUseProgram(shader); + if( need_matrix ) BC_GL_YUV_TO_RGB(shader); // Set texture unit of the texture - glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0); + glUniform1i(glGetUniformLocation(shader, "tex"), 0); // Set texture unit of the temp texture - glUniform1i(glGetUniformLocation(frag_shader, "tex2"), 1); + glUniform1i(glGetUniformLocation(shader, "tex2"), 1); // Set alpha - int variable = glGetUniformLocation(frag_shader, "alpha"); + int variable = glGetUniformLocation(shader, "alpha"); glUniform1f(variable, command->alpha); // Set dimensions of the temp texture if(temp_texture) - glUniform2f(glGetUniformLocation(frag_shader, "tex2_dimensions"), + glUniform2f(glGetUniformLocation(shader, "tex2_dimensions"), (float)temp_texture->get_texture_w(), (float)temp_texture->get_texture_h()); } @@ -1260,15 +1072,14 @@ void Playback3D::overlay_sync(Playback3DCommand *command) glUseProgram(0); -// printf("Playback3D::overlay_sync %f %f %f %f %f %f %f %f\n", +//printf("Playback3D::overlay_sync %f %f %f %f %f %f %f %f\n", // command->in_x1, command->in_y1, command->in_x2, command->in_y2, // command->out_x1, command->out_y1, command->out_x2, command->out_y2); command->input->draw_texture( command->in_x1, command->in_y1, command->in_x2, command->in_y2, command->out_x1, command->out_y1, command->out_x2, command->out_y2, -// Don't flip vertical if nested - command->is_nested > 0 ? 0 : 1); + !command->is_nested); glUseProgram(0); // Delete temp texture @@ -1440,6 +1251,7 @@ void Playback3D::do_mask_sync(Playback3DCommand *command) // Need to tabulate every vertex in persistent memory because // gluTessVertex doesn't copy them. ArrayList coords; + coords.set_array_delete(); for(int i = 0; i < points->total; i++) { MaskPoint *point1 = points->values[i]; @@ -1578,27 +1390,19 @@ void Playback3D::do_mask_sync(Playback3DCommand *command) // For unfeathered masks, we could use a stencil buffer // for further optimization but we also need a YUV algorithm. unsigned int frag_shader = 0; - switch(temp_texture->get_texture_components()) - { - case 3: - if(command->frame->get_color_model() == BC_YUV888) - frag_shader = VFrame::make_shader(0, - multiply_yuvmask3_frag, - 0); - else - frag_shader = VFrame::make_shader(0, - multiply_mask3_frag, - 0); - break; - case 4: - frag_shader = VFrame::make_shader(0, - multiply_mask4_frag, - 0); - break; + switch(temp_texture->get_texture_components()) { + case 3: + frag_shader = VFrame::make_shader(0, + command->frame->get_color_model() == BC_YUV888 ? + multiply_yuvmask3_frag : multiply_mask3_frag, + 0); + break; + case 4: + frag_shader = VFrame::make_shader(0, multiply_mask4_frag, 0); + break; } - if(frag_shader) - { + if( frag_shader ) { int variable; glUseProgram(frag_shader); if((variable = glGetUniformLocation(frag_shader, "tex")) >= 0) @@ -1681,8 +1485,7 @@ void Playback3D::convert_cmodel_sync(Playback3DCommand *command) #ifdef HAVE_GL command->canvas->lock_canvas("Playback3D::convert_cmodel_sync"); - if(command->canvas->get_canvas()) - { + if( command->canvas->get_canvas() ) { BC_WindowBase *window = command->canvas->get_canvas(); window->lock_window("Playback3D::convert_cmodel_sync"); window->enable_opengl(); @@ -1693,47 +1496,45 @@ void Playback3D::convert_cmodel_sync(Playback3DCommand *command) command->frame->to_texture(); // Colormodel permutation - const char *shader = 0; int src_cmodel = command->frame->get_color_model(); int dst_cmodel = command->dst_cmodel; - typedef struct - { - int src; - int dst; + typedef struct { + int src, dst, typ; const char *shader; } cmodel_shader_table_t; - static cmodel_shader_table_t cmodel_shader_table[] = - { - { BC_RGB888, BC_YUV888, rgb_to_yuv_frag }, - { BC_RGB888, BC_YUVA8888, rgb_to_yuv_frag }, - { BC_RGBA8888, BC_RGB888, rgba_to_rgb_frag }, - { BC_RGBA8888, BC_RGB_FLOAT, rgba_to_rgb_frag }, - { BC_RGBA8888, BC_YUV888, rgba_to_yuv_frag }, - { BC_RGBA8888, BC_YUVA8888, rgb_to_yuv_frag }, - { BC_RGB_FLOAT, BC_YUV888, rgb_to_yuv_frag }, - { BC_RGB_FLOAT, BC_YUVA8888, rgb_to_yuv_frag }, - { BC_RGBA_FLOAT, BC_RGB888, rgba_to_rgb_frag }, - { BC_RGBA_FLOAT, BC_RGB_FLOAT, rgba_to_rgb_frag }, - { BC_RGBA_FLOAT, BC_YUV888, rgba_to_yuv_frag }, - { BC_RGBA_FLOAT, BC_YUVA8888, rgb_to_yuv_frag }, - { BC_YUV888, BC_RGB888, yuv_to_rgb_frag }, - { BC_YUV888, BC_RGBA8888, yuv_to_rgb_frag }, - { BC_YUV888, BC_RGB_FLOAT, yuv_to_rgb_frag }, - { BC_YUV888, BC_RGBA_FLOAT, yuv_to_rgb_frag }, - { BC_YUVA8888, BC_RGB888, yuva_to_rgb_frag }, - { BC_YUVA8888, BC_RGBA8888, yuv_to_rgb_frag }, - { BC_YUVA8888, BC_RGB_FLOAT, yuva_to_rgb_frag }, - { BC_YUVA8888, BC_RGBA_FLOAT, yuv_to_rgb_frag }, - { BC_YUVA8888, BC_YUV888, yuva_to_yuv_frag }, + enum { rgb_to_rgb, rgb_to_yuv, yuv_to_rgb, yuv_to_yuv, }; + int type = -1; + static cmodel_shader_table_t cmodel_shader_table[] = { + { BC_RGB888, BC_YUV888, rgb_to_yuv, rgb_to_yuv_frag }, + { BC_RGB888, BC_YUVA8888, rgb_to_yuv, rgb_to_yuv_frag }, + { BC_RGBA8888, BC_RGB888, rgb_to_rgb, rgba_to_rgb_frag }, + { BC_RGBA8888, BC_RGB_FLOAT, rgb_to_rgb, rgba_to_rgb_frag }, + { BC_RGBA8888, BC_YUV888, rgb_to_yuv, rgba_to_yuv_frag }, + { BC_RGBA8888, BC_YUVA8888, rgb_to_yuv, rgb_to_yuv_frag }, + { BC_RGB_FLOAT, BC_YUV888, rgb_to_yuv, rgb_to_yuv_frag }, + { BC_RGB_FLOAT, BC_YUVA8888, rgb_to_yuv, rgb_to_yuv_frag }, + { BC_RGBA_FLOAT,BC_RGB888, rgb_to_rgb, rgba_to_rgb_frag }, + { BC_RGBA_FLOAT,BC_RGB_FLOAT, rgb_to_rgb, rgba_to_rgb_frag }, + { BC_RGBA_FLOAT,BC_YUV888, rgb_to_yuv, rgba_to_yuv_frag }, + { BC_RGBA_FLOAT,BC_YUVA8888, rgb_to_yuv, rgb_to_yuv_frag }, + { BC_YUV888, BC_RGB888, yuv_to_rgb, yuv_to_rgb_frag }, + { BC_YUV888, BC_RGBA8888, yuv_to_rgb, yuv_to_rgb_frag }, + { BC_YUV888, BC_RGB_FLOAT, yuv_to_rgb, yuv_to_rgb_frag }, + { BC_YUV888, BC_RGBA_FLOAT, yuv_to_rgb, yuv_to_rgb_frag }, + { BC_YUVA8888, BC_RGB888, yuv_to_rgb, yuva_to_rgb_frag }, + { BC_YUVA8888, BC_RGBA8888, yuv_to_rgb, yuv_to_rgb_frag }, + { BC_YUVA8888, BC_RGB_FLOAT, yuv_to_rgb, yuva_to_rgb_frag }, + { BC_YUVA8888, BC_RGBA_FLOAT, yuv_to_rgb, yuv_to_rgb_frag }, + { BC_YUVA8888, BC_YUV888, yuv_to_yuv, yuva_to_yuv_frag }, }; + const char *shader = 0; int table_size = sizeof(cmodel_shader_table) / sizeof(cmodel_shader_table_t); - for(int i = 0; i < table_size; i++) - { - if(cmodel_shader_table[i].src == src_cmodel && - cmodel_shader_table[i].dst == dst_cmodel) - { + for( int i=0; idst_cmodel, // shader); - if(shader) - { + const char *shader_stack[9]; + memset(shader_stack,0, sizeof(shader_stack)); + int current_shader = 0; + + if( shader ) { //printf("Playback3D::convert_cmodel_sync %d\n", __LINE__); + shader_stack[current_shader++] = shader; + shader_stack[current_shader] = 0; + unsigned int shader_id = VFrame::make_shader(shader_stack); + command->frame->bind_texture(0); - unsigned int shader_id = -1; - if(shader) - { - shader_id = VFrame::make_shader(0, - shader, - 0); - glUseProgram(shader_id); - glUniform1i(glGetUniformLocation(shader_id, "tex"), 0); + glUseProgram(shader_id); + + glUniform1i(glGetUniformLocation(shader_id, "tex"), 0); + switch( type ) { + case rgb_to_yuv: + BC_GL_RGB_TO_YUV(shader_id); + break; + case yuv_to_rgb: + BC_GL_YUV_TO_RGB(shader_id); + break; } command->frame->draw_texture(); - if(shader) glUseProgram(0); - command->frame->set_opengl_state(VFrame::SCREEN); } @@ -1838,8 +1646,7 @@ void Playback3D::do_fade_sync(Playback3DCommand *command) } - if(frag_shader) - { + if( frag_shader ) { glUseProgram(frag_shader); int variable; if((variable = glGetUniformLocation(frag_shader, "tex")) >= 0)