X-Git-Url: https://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fplayback3d.C;h=672d7a2fd4b5cc9120697cb42425536347c991a8;hb=620f70a943c1f47880ec68a908aa03bf463e741f;hp=aefafc8e3f9c7c61fb5cbe71cc56494fc16a75e0;hpb=7ead9f7382846e81c2f8efb25780014e5f8834c3;p=goodguy%2Fcinelerra.git diff --git a/cinelerra-5.1/cinelerra/playback3d.C b/cinelerra-5.1/cinelerra/playback3d.C index aefafc8e..672d7a2f 100644 --- a/cinelerra-5.1/cinelerra/playback3d.C +++ b/cinelerra-5.1/cinelerra/playback3d.C @@ -38,6 +38,7 @@ #include "pluginclient.h" #include "pluginvclient.h" #include "edlsession.h" +#include "track.h" #include "transportque.inc" #include "vframe.h" @@ -295,14 +296,35 @@ static const char *feather_frag = " }\n" "}\n"; -static const char *alpha_frag = +static const char *multiply_mask4_frag = "uniform sampler2D tex;\n" - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "void main() {\n" \ + "uniform sampler2D tex1;\n" + "void main()\n" + "{\n" " gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " gl_FragColor.a = canvas.a;\n" + " gl_FragColor.a *= texture2D(tex1, gl_TexCoord[0].st).r;\n" + "}\n"; + +static const char *multiply_mask3_frag = + "uniform sampler2D tex;\n" + "uniform sampler2D tex1;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" + " float a = texture2D(tex1, gl_TexCoord[0].st).r;\n" + " gl_FragColor.rgb *= vec3(a, a, a);\n" + "}\n"; + +static const char *multiply_yuvmask3_frag = + "uniform sampler2D tex;\n" + "uniform sampler2D tex1;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" + " float a = texture2D(tex1, gl_TexCoord[0].st).r;\n" + " gl_FragColor.gb -= vec2(0.5, 0.5);\n" + " gl_FragColor.rgb *= vec3(a, a, a);\n" + " gl_FragColor.gb += vec2(0.5, 0.5);\n" "}\n"; static const char *fade_rgba_frag = @@ -368,32 +390,11 @@ void Playback3DCommand::copy_from(BC_SynchronousCommand *command) BC_SynchronousCommand::copy_from(command); } -//#define GL_BUG 1 -#ifdef GL_BUG -static void GLAPIENTRY glDebugCallback(GLenum source, GLenum type, - GLuint id, GLenum severity, GLsizei length, const GLchar* message, - const void* userParam) -{ - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), - type, severity, message ); -} -#endif - Playback3D::Playback3D(MWindow *mwindow) : BC_Synchronous() { this->mwindow = mwindow; temp_texture = 0; -#ifdef GL_BUG - //Enabling OpenGL debug output - // this does not work - glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); - glEnable(GL_DEBUG_OUTPUT); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - glDebugMessageCallback(glDebugCallback, 0); - glEnable(GL_DEBUG_OUTPUT); -#endif } Playback3D::~Playback3D() @@ -419,10 +420,6 @@ void Playback3D::handle_command(BC_SynchronousCommand *command) write_buffer_sync((Playback3DCommand*)command); break; - case Playback3DCommand::FINISH_OUTPUT: - finish_output_sync((Playback3DCommand*)command); - break; - case Playback3DCommand::CLEAR_OUTPUT: clear_output_sync((Playback3DCommand*)command); break; @@ -490,6 +487,7 @@ void Playback3D::copy_from_sync(Playback3DCommand *command) command->canvas->lock_canvas("Playback3D::copy_from_sync"); if( window ) { window->enable_opengl(); + glFinish(); int w = command->input->get_w(); int h = command->input->get_h(); @@ -658,35 +656,21 @@ void Playback3D::write_buffer_sync(Playback3DCommand *command) BC_WindowBase *window = command->canvas->lock_canvas("Playback3D::write_buffer_sync"); if( window ) { + window->enable_opengl(); // Update hidden cursor window->update_video_cursor(); -// Make sure OpenGL is enabled first. - window->enable_opengl(); - + command->frame->enable_opengl(); + command->frame->init_screen(); //printf("Playback3D::write_buffer_sync 1 %d\n", window->get_id()); - 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(); - window->enable_opengl(); -// Composite texture to screen and swap buffer - case VFrame::TEXTURE: - 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; + int frame_state = command->frame->get_opengl_state(); + if( frame_state != VFrame::TEXTURE ) + command->frame->to_texture(); + if( frame_state != VFrame::RAM ) { + command->in_y1 = command->frame->get_h() - command->in_y1; + command->in_y2 = command->frame->get_h() - command->in_y2; } + window->enable_opengl(); + draw_output(command, 1); command->frame->set_opengl_state(frame_state); } command->canvas->unlock_canvas(); @@ -751,14 +735,8 @@ void Playback3D::draw_output(Playback3DCommand *command, int flip_y) //printf("Playback3D::draw_output 2 %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->in_x1, command->in_y1, command->in_x2, command->in_y2, +// command->out_x1, command->out_y1, command->out_x2, command->out_y2); glUseProgram(0); @@ -779,28 +757,6 @@ void Playback3D::init_frame(Playback3DCommand *command, int is_yuv) } -void Playback3D::finish_output(Canvas *canvas) -{ - Playback3DCommand command; - command.canvas = canvas; - command.command = Playback3DCommand::FINISH_OUTPUT; - send_command(&command); -} - -void Playback3D::finish_output_sync(Playback3DCommand *command) -{ -#ifdef HAVE_GL - BC_WindowBase *window = - command->canvas->lock_canvas("Playback3D::finish_output_sync"); - if( window ) { - command->canvas->get_canvas()->enable_opengl(); - glFinish(); - } - command->canvas->unlock_canvas(); -#endif -} - - void Playback3D::clear_output(Canvas *canvas, VFrame *output) { Playback3DCommand command; @@ -1269,10 +1225,12 @@ static void combineData(GLdouble coords[3], vertex[1] = coords[1]; vertex[2] = coords[2]; for( int i=3; i<6; ++i ) { - vertex[i] = weight[0] * vertex_data[0][i] + - weight[1] * vertex_data[1][i] + - weight[2] * vertex_data[2][i] + - weight[3] * vertex_data[3][i]; + GLdouble v = 0; + for( int k=0; k<4; ++k ) { + if( !weight[k] || !vertex_data[k] ) continue; + v += weight[k] * vertex_data[k][i]; + } + vertex[i] = v; } *outData = vertex; } @@ -1314,13 +1272,13 @@ void Playback3D::do_mask_sync(Playback3DCommand *command) int h = command->frame->get_h(); MaskEdges edges; float faders[SUBMASKS], feathers[SUBMASKS], bg = 1; - MaskPointSet point_set[SUBMASKS]; + MaskPoints point_set[SUBMASKS]; // Draw every submask as a new polygon int total_submasks = command->keyframe_set->total_submasks( command->start_position_project, PLAY_FORWARD); for(int k = 0; k < total_submasks; k++) { - MaskPointSet &points = point_set[k]; + MaskPoints &points = point_set[k]; command->keyframe_set->get_points(&points, k, command->start_position_project, PLAY_FORWARD); float fader = command->keyframe_set->get_fader( @@ -1337,81 +1295,11 @@ void Playback3D::do_mask_sync(Playback3DCommand *command) glClearColor(bg, bg, bg, bg); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + int show_mask = command->keyframe_set->track->masks; for(int k = 0; k < total_submasks; k++) { - MaskPointSet &points = point_set[k]; MaskEdge &edge = *edges.append(new MaskEdge()); - int first_point = 0; -// Need to tabulate every vertex in persistent memory because -// gluTessVertex doesn't copy them. - for(int i = 0; i < points.total; i++) { - MaskPoint *point1 = points.values[i]; - MaskPoint *point2 = (i >= points.total - 1) ? - points.values[0] : points.values[i + 1]; - - float x, y; - int segments = 0; - if( point1->control_x2 == 0 && point1->control_y2 == 0 && - point2->control_x1 == 0 && point2->control_y1 == 0 ) - segments = 1; - - float x0 = point1->x, y0 = point1->y; - float x1 = point1->x + point1->control_x2; - float y1 = point1->y + point1->control_y2; - float x2 = point2->x + point2->control_x1; - float y2 = point2->y + point2->control_y1; - float x3 = point2->x, y3 = point2->y; - - // forward differencing bezier curves implementation taken from GPL code at - // http://cvs.sourceforge.net/viewcvs.py/guliverkli/guliverkli/src/subtitles/Rasterizer.cpp?rev=1.3 - - float cx3, cx2, cx1, cx0, cy3, cy2, cy1, cy0; - - // [-1 +3 -3 +1] - // [+3 -6 +3 0] - // [-3 +3 0 0] - // [+1 0 0 0] - - cx3 = - x0 + 3*x1 - 3*x2 + x3; - cx2 = 3*x0 - 6*x1 + 3*x2; - cx1 = -3*x0 + 3*x1; - cx0 = x0; - - cy3 = - y0 + 3*y1 - 3*y2 + y3; - cy2 = 3*y0 - 6*y1 + 3*y2; - cy1 = -3*y0 + 3*y1; - cy0 = y0; - - // This equation is from Graphics Gems I. - // - // The idea is that since we're approximating a cubic curve with lines, - // any error we incur is due to the curvature of the line, which we can - // estimate by calculating the maximum acceleration of the curve. For - // a cubic, the acceleration (second derivative) is a line, meaning that - // the absolute maximum acceleration must occur at either the beginning - // (|c2|) or the end (|c2+c3|). Our bounds here are a little more - // conservative than that, but that's okay. - if (segments == 0) { - float maxaccel1 = fabs(2*cy2) + fabs(6*cy3); - float maxaccel2 = fabs(2*cx2) + fabs(6*cx3); - - float maxaccel = maxaccel1 > maxaccel2 ? maxaccel1 : maxaccel2; - float h = 1.0; - - if(maxaccel > 8.0) h = sqrt((8.0) / maxaccel); - segments = int(1/h); - } - - for(int j = 0; j <= segments; j++) { - float t = (float)j / segments; - x = cx0 + t*(cx1 + t*(cx2 + t*cx3)); - y = cy0 + t*(cy1 + t*(cy2 + t*cy3)); - - if(j > 0 || first_point) { - edge.append(x, y - h); - first_point = 0; - } - } - } + if( !((show_mask>>k) & 1) ) continue; + edge.load(point_set[k], h); if( edge.size() > 0 ) { // draw polygon float fader = faders[k]; @@ -1495,20 +1383,18 @@ void Playback3D::do_mask_sync(Playback3DCommand *command) glDrawBuffers(0, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); - unsigned int shader = VFrame::make_shader(0, alpha_frag, 0); + const char *alpha_shader = BC_CModels::has_alpha(color_model) ? + multiply_mask4_frag : + !BC_CModels::is_yuv(color_model) ? + multiply_mask3_frag : + multiply_yuvmask3_frag; + unsigned int shader = VFrame::make_shader(0, alpha_shader, 0); glUseProgram(shader); if( shader > 0 ) { command->frame->bind_texture(0); in->BC_Texture::bind(1); glUniform1i(glGetUniformLocation(shader, "tex"), 0); - glUniform1i(glGetUniformLocation(shader, "tex2"), 1); - glUniform2f(glGetUniformLocation(shader, "tex2_dimensions"), - (float)in->get_texture_w(), - (float)in->get_texture_h()); -// if( BC_CModels::components(color_model ) == 4) { -// glEnable(GL_BLEND); -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// } + glUniform1i(glGetUniformLocation(shader, "tex1"), 1); } command->frame->draw_texture(); command->frame->set_opengl_state(VFrame::SCREEN);