void Playback3D::write_buffer_sync(Playback3DCommand *command) { command->canvas->lock_canvas("Playback3D::write_buffer_sync"); if(command->canvas->get_canvas()) { BC_WindowBase *window = command->canvas->get_canvas(); window->lock_window("Playback3D::write_buffer_sync"); // Update hidden cursor window->update_video_cursor(); // 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()) { // Upload texture and composite to screen case VFrame::RAM: command->frame->to_texture(); draw_output(command); break; // Composite texture to screen and swap buffer case VFrame::TEXTURE: draw_output(command); break; case VFrame::SCREEN: // swap buffers only window->flip_opengl(); break; default: printf("Playback3D::write_buffer_sync unknown state\n"); break; } window->unlock_window(); } command->canvas->unlock_canvas(); }
void Playback3D::overlay_sync(Playback3DCommand *command) { #ifdef HAVE_GL command->canvas->lock_canvas("Playback3D::overlay_sync"); if(command->canvas->get_canvas()) { BC_WindowBase *window = command->canvas->get_canvas(); window->lock_window("Playback3D::overlay_sync"); // Make sure OpenGL is enabled first. window->enable_opengl(); window->update_video_cursor(); // Render to PBuffer if(command->frame) { 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(); } glColor4f(1, 1, 1, 1); //printf("Playback3D::overlay_sync 1 %d\n", command->input->get_opengl_state()); switch(command->input->get_opengl_state()) { // Upload texture and composite to screen case VFrame::RAM: command->input->to_texture(); break; // Just composite texture to screen case VFrame::TEXTURE: break; // read from PBuffer to texture, then composite texture to screen 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; } const char *shader_stack[3] = { 0, 0, 0 }; int total_shaders = 0; VFrame::init_screen(canvas_w, canvas_h); // Enable texture command->input->bind_texture(0); // Convert colormodel to RGB if not nested. // The color model setting in the output frame is ignored. if(!command->is_nested) { switch(command->input->get_color_model()) { case BC_YUV888: case BC_YUVA8888: shader_stack[total_shaders++] = yuv_to_rgb_frag; break; } } // Change blend operation switch(command->mode) { case TRANSFER_NORMAL: glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; case TRANSFER_REPLACE: // This requires overlaying an alpha multiplied image on a black screen. glDisable(GL_BLEND); if(command->input->get_texture_components() == 4) { if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; shader_stack[total_shaders++] = multiply_alpha_frag; } break; // To do these operations, we need to copy the input buffer to a texture // and blend 2 textures in another shader case TRANSFER_ADDITION: enable_overlay_texture(command); if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; shader_stack[total_shaders++] = blend_add_frag; break; case TRANSFER_SUBTRACT: enable_overlay_texture(command); if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; shader_stack[total_shaders++] = blend_subtract_frag; break; case TRANSFER_MULTIPLY: enable_overlay_texture(command); if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; shader_stack[total_shaders++] = blend_multiply_frag; break; case TRANSFER_MAX: enable_overlay_texture(command); if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; shader_stack[total_shaders++] = blend_max_frag; break; case TRANSFER_MIN: enable_overlay_texture(command); if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; shader_stack[total_shaders++] = blend_min_frag; break; case TRANSFER_DIVIDE: enable_overlay_texture(command); if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; shader_stack[total_shaders++] = blend_divide_frag; break; } unsigned int frag_shader = 0; if(shader_stack[0]) { frag_shader = VFrame::make_shader(0, shader_stack[0], shader_stack[1], 0); glUseProgram(frag_shader); // Set texture unit of the texture glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0); // Set texture unit of the temp texture glUniform1i(glGetUniformLocation(frag_shader, "tex2"), 1); // Set dimensions of the temp texture if(temp_texture) glUniform2f(glGetUniformLocation(frag_shader, "tex2_dimensions"), (float)temp_texture->get_texture_w(), (float)temp_texture->get_texture_h()); } else glUseProgram(0); // 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); glUseProgram(0); // Delete temp texture if(temp_texture) { delete temp_texture; temp_texture = 0; glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); } glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); window->unlock_window(); } command->canvas->unlock_canvas(); #endif }
void Playback3D::overlay_sync(Playback3DCommand *command) { #ifdef HAVE_GL // 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 }; command->canvas->lock_canvas("Playback3D::overlay_sync"); if(command->canvas->get_canvas()) { BC_WindowBase *window = command->canvas->get_canvas(); window->lock_window("Playback3D::overlay_sync"); // Make sure OpenGL is enabled first. window->enable_opengl(); window->update_video_cursor(); 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()) { // Upload texture and composite to screen case VFrame::RAM: command->input->to_texture(); break; // Just composite texture to screen case VFrame::TEXTURE: break; // read from PBuffer to texture, then composite texture to screen 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; } const char *shader_stack[4] = { 0, 0, 0, 0, }; int total_shaders = 0; VFrame::init_screen(canvas_w, canvas_h); // Enable texture command->input->bind_texture(0); // 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; } } // get the shaders #define add_shader(s) \ if(!total_shaders) shader_stack[total_shaders++] = read_texture_frag; \ shader_stack[total_shaders++] = s switch(command->mode) { case TRANSFER_REPLACE: // This requires overlaying an alpha multiplied image on a black screen. if( command->input->get_texture_components() != 4 ) break; add_shader(overlay_shaders[command->mode]); break; default: enable_overlay_texture(command); add_shader(overlay_shaders[command->mode]); break; } // 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; } } // 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); // Set texture unit of the texture glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0); // Set texture unit of the temp texture glUniform1i(glGetUniformLocation(frag_shader, "tex2"), 1); // Set alpha int variable = glGetUniformLocation(frag_shader, "alpha"); glUniform1f(variable, command->alpha); // Set dimensions of the temp texture if(temp_texture) glUniform2f(glGetUniformLocation(frag_shader, "tex2_dimensions"), (float)temp_texture->get_texture_w(), (float)temp_texture->get_texture_h()); } else glUseProgram(0); // 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); glUseProgram(0); // Delete temp texture if(temp_texture) { delete temp_texture; temp_texture = 0; glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); } glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); window->unlock_window(); } command->canvas->unlock_canvas(); #endif }