2016-02-14 01:52:23 +00:00
//
// CRTOpenGL.hpp
// Clock Signal
//
// Created by Thomas Harte on 13/02/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
# ifndef CRTOpenGL_h
# define CRTOpenGL_h
2016-03-09 03:40:23 +00:00
# include "../CRTTypes.hpp"
2016-03-19 21:07:05 +00:00
# include "CRTConstants.hpp"
2016-03-09 03:40:23 +00:00
# include "OpenGL.hpp"
# include "TextureTarget.hpp"
2017-11-09 03:36:41 +00:00
# include "Shaders/Shader.hpp"
2016-11-17 04:26:04 +00:00
# include "ArrayBuilder.hpp"
2016-11-16 14:57:17 +00:00
# include "TextureBuilder.hpp"
2016-03-09 03:40:23 +00:00
2016-04-28 02:29:54 +00:00
# include "Shaders/OutputShader.hpp"
2016-04-29 01:45:44 +00:00
# include "Shaders/IntermediateShader.hpp"
2016-04-28 02:29:54 +00:00
2016-03-09 03:40:23 +00:00
# include <mutex>
2016-11-16 02:34:54 +00:00
# include <vector>
2016-03-09 03:40:23 +00:00
2016-03-09 01:49:07 +00:00
namespace Outputs {
namespace CRT {
2016-03-09 03:40:23 +00:00
class OpenGLOutputBuilder {
private :
// colour information
2016-11-21 04:14:52 +00:00
ColourSpace colour_space_ ;
unsigned int colour_cycle_numerator_ ;
unsigned int colour_cycle_denominator_ ;
2018-03-30 14:25:41 +00:00
VideoSignal video_signal_ ;
2017-08-10 19:17:08 +00:00
float gamma_ ;
2016-03-09 03:40:23 +00:00
// timing information to allow reasoning about input information
2016-11-21 04:14:52 +00:00
unsigned int input_frequency_ ;
unsigned int cycles_per_line_ ;
unsigned int height_of_display_ ;
unsigned int horizontal_scan_period_ ;
unsigned int vertical_scan_period_ ;
unsigned int vertical_period_divider_ ;
2016-03-09 03:40:23 +00:00
// The user-supplied visible area
2016-11-21 04:14:52 +00:00
Rect visible_area_ ;
2016-03-09 03:40:23 +00:00
// Other things the caller may have provided.
2017-02-20 15:35:33 +00:00
std : : string composite_shader_ ;
2018-03-30 16:41:20 +00:00
std : : string svideo_shader_ ;
2017-02-20 15:35:33 +00:00
std : : string rgb_shader_ ;
2017-11-13 00:29:22 +00:00
GLint target_framebuffer_ = 0 ;
2016-03-09 03:40:23 +00:00
// Methods used by the OpenGL code
2016-05-03 01:05:58 +00:00
void prepare_output_shader ( ) ;
void prepare_rgb_input_shaders ( ) ;
2018-03-30 16:41:20 +00:00
void prepare_svideo_input_shaders ( ) ;
2016-05-03 01:05:58 +00:00
void prepare_composite_input_shaders ( ) ;
2016-04-22 00:21:34 +00:00
2016-03-09 03:40:23 +00:00
void prepare_output_vertex_array ( ) ;
2016-04-17 20:17:23 +00:00
void prepare_source_vertex_array ( ) ;
2016-03-09 03:40:23 +00:00
// the run and input data buffers
2016-11-21 04:14:52 +00:00
std : : mutex output_mutex_ ;
std : : mutex draw_mutex_ ;
2016-03-09 03:40:23 +00:00
// transient buffers indicating composite data not yet decoded
2016-11-21 04:14:52 +00:00
GLsizei composite_src_output_y_ ;
2016-03-09 03:40:23 +00:00
2016-11-21 04:14:52 +00:00
std : : unique_ptr < OpenGL : : OutputShader > output_shader_program_ ;
2016-03-09 03:40:23 +00:00
2017-01-08 16:13:20 +00:00
std : : unique_ptr < OpenGL : : IntermediateShader > composite_input_shader_program_ ;
std : : unique_ptr < OpenGL : : IntermediateShader > composite_separation_filter_program_ ;
std : : unique_ptr < OpenGL : : IntermediateShader > composite_chrominance_filter_shader_program_ ;
2018-03-30 14:25:41 +00:00
std : : unique_ptr < OpenGL : : IntermediateShader > svideo_input_shader_program_ ;
2017-01-08 16:13:20 +00:00
std : : unique_ptr < OpenGL : : IntermediateShader > rgb_input_shader_program_ ;
std : : unique_ptr < OpenGL : : IntermediateShader > rgb_filter_shader_program_ ;
std : : unique_ptr < OpenGL : : TextureTarget > composite_texture_ ; // receives raw composite levels
std : : unique_ptr < OpenGL : : TextureTarget > separated_texture_ ; // receives filtered Y in the R channel plus unfiltered but demodulated chrominance in G and B
std : : unique_ptr < OpenGL : : TextureTarget > filtered_texture_ ; // receives filtered YIQ or YUV
std : : unique_ptr < OpenGL : : TextureTarget > work_texture_ ; // used for all intermediate rendering if texture fences are supported
2016-05-03 11:46:40 +00:00
2016-11-21 04:14:52 +00:00
std : : unique_ptr < OpenGL : : TextureTarget > framebuffer_ ; // the current pixel output
2016-05-03 11:46:40 +00:00
2016-11-21 04:14:52 +00:00
GLuint output_vertex_array_ ;
GLuint source_vertex_array_ ;
2016-03-09 03:40:23 +00:00
2016-11-21 04:14:52 +00:00
unsigned int last_output_width_ , last_output_height_ ;
2016-03-09 03:40:23 +00:00
2016-04-24 22:58:31 +00:00
void set_timing_uniforms ( ) ;
2016-04-24 23:16:23 +00:00
void set_colour_space_uniforms ( ) ;
2017-08-10 19:17:08 +00:00
void set_gamma ( ) ;
2016-04-17 22:08:05 +00:00
2016-05-12 02:11:01 +00:00
void establish_OpenGL_state ( ) ;
void reset_all_OpenGL_state ( ) ;
2016-11-21 04:14:52 +00:00
GLsync fence_ ;
2017-01-25 01:48:54 +00:00
float get_composite_output_width ( ) const ;
void set_output_shader_width ( ) ;
2016-11-21 04:14:52 +00:00
2016-03-09 03:40:23 +00:00
public :
2016-12-06 23:48:30 +00:00
// These two are protected by output_mutex_.
2016-11-17 04:26:04 +00:00
TextureBuilder texture_builder ;
ArrayBuilder array_builder ;
2016-03-09 03:40:23 +00:00
2017-11-11 20:28:40 +00:00
OpenGLOutputBuilder ( std : : size_t bytes_per_pixel ) ;
2016-11-17 04:26:04 +00:00
~ OpenGLOutputBuilder ( ) ;
2016-03-09 03:40:23 +00:00
2017-03-26 18:34:47 +00:00
inline void set_colour_format ( ColourSpace colour_space , unsigned int colour_cycle_numerator , unsigned int colour_cycle_denominator ) {
2016-12-06 23:48:30 +00:00
std : : lock_guard < std : : mutex > output_guard ( output_mutex_ ) ;
2016-11-21 04:14:52 +00:00
colour_space_ = colour_space ;
colour_cycle_numerator_ = colour_cycle_numerator ;
colour_cycle_denominator_ = colour_cycle_denominator ;
2016-11-16 02:34:54 +00:00
set_colour_space_uniforms ( ) ;
2016-05-07 22:37:18 +00:00
}
2017-03-26 18:34:47 +00:00
inline void set_visible_area ( Rect visible_area ) {
2016-11-21 04:14:52 +00:00
visible_area_ = visible_area ;
2016-03-09 03:40:23 +00:00
}
2017-08-10 19:17:08 +00:00
inline void set_gamma ( float gamma ) {
gamma_ = gamma ;
set_gamma ( ) ;
}
2017-03-26 18:34:47 +00:00
inline std : : unique_lock < std : : mutex > get_output_lock ( ) {
2016-12-06 23:48:30 +00:00
return std : : unique_lock < std : : mutex > ( output_mutex_ ) ;
2016-03-09 03:40:23 +00:00
}
2018-03-30 14:25:41 +00:00
inline VideoSignal get_output_device ( ) {
return video_signal_ ;
2016-03-09 03:40:23 +00:00
}
2017-03-26 18:34:47 +00:00
inline uint16_t get_composite_output_y ( ) {
2017-10-22 01:50:53 +00:00
return static_cast < uint16_t > ( composite_src_output_y_ ) ;
2016-03-09 03:40:23 +00:00
}
2017-03-26 18:34:47 +00:00
inline bool composite_output_buffer_is_full ( ) {
2016-11-21 04:14:52 +00:00
return composite_src_output_y_ = = IntermediateBufferHeight ;
2016-05-07 22:37:18 +00:00
}
2017-03-26 18:34:47 +00:00
inline void increment_composite_output_y ( ) {
2016-05-07 22:37:18 +00:00
if ( ! composite_output_buffer_is_full ( ) )
2016-11-21 04:14:52 +00:00
composite_src_output_y_ + + ;
2016-03-09 03:40:23 +00:00
}
2017-11-13 00:29:22 +00:00
2018-03-30 14:25:41 +00:00
void set_target_framebuffer ( GLint ) ;
2016-03-09 03:40:23 +00:00
void draw_frame ( unsigned int output_width , unsigned int output_height , bool only_if_dirty ) ;
void set_openGL_context_will_change ( bool should_delete_resources ) ;
2018-03-30 14:25:41 +00:00
void set_composite_sampling_function ( const std : : string & ) ;
void set_svideo_sampling_function ( const std : : string & ) ;
void set_rgb_sampling_function ( const std : : string & ) ;
void set_video_signal ( VideoSignal ) ;
2016-05-03 01:05:58 +00:00
void set_timing ( unsigned int input_frequency , unsigned int cycles_per_line , unsigned int height_of_display , unsigned int horizontal_scan_period , unsigned int vertical_scan_period , unsigned int vertical_period_divider ) ;
2016-03-09 03:40:23 +00:00
} ;
2016-03-09 01:49:07 +00:00
}
}
2016-02-14 04:50:18 +00:00
2016-02-14 01:52:23 +00:00
# endif /* CRTOpenGL_h */