// // 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 #include "../CRTTypes.hpp" #include "CRTConstants.hpp" #include "OpenGL.hpp" #include "TextureTarget.hpp" #include "Shader.hpp" #include "ArrayBuilder.hpp" #include "TextureBuilder.hpp" #include "Shaders/OutputShader.hpp" #include "Shaders/IntermediateShader.hpp" #include #include namespace Outputs { namespace CRT { class OpenGLOutputBuilder { private: // colour information ColourSpace colour_space_; unsigned int colour_cycle_numerator_; unsigned int colour_cycle_denominator_; OutputDevice output_device_; float gamma_; // timing information to allow reasoning about input information 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_; // The user-supplied visible area Rect visible_area_; // Other things the caller may have provided. std::string composite_shader_; std::string rgb_shader_; // Methods used by the OpenGL code void prepare_output_shader(); void prepare_rgb_input_shaders(); void prepare_composite_input_shaders(); void prepare_output_vertex_array(); void prepare_source_vertex_array(); // the run and input data buffers std::mutex output_mutex_; std::mutex draw_mutex_; // transient buffers indicating composite data not yet decoded GLsizei composite_src_output_y_; std::unique_ptr output_shader_program_; std::unique_ptr composite_input_shader_program_; std::unique_ptr composite_separation_filter_program_; std::unique_ptr composite_chrominance_filter_shader_program_; std::unique_ptr rgb_input_shader_program_; std::unique_ptr rgb_filter_shader_program_; std::unique_ptr composite_texture_; // receives raw composite levels std::unique_ptr separated_texture_; // receives filtered Y in the R channel plus unfiltered but demodulated chrominance in G and B std::unique_ptr filtered_texture_; // receives filtered YIQ or YUV std::unique_ptr work_texture_; // used for all intermediate rendering if texture fences are supported std::unique_ptr framebuffer_; // the current pixel output GLuint output_vertex_array_; GLuint source_vertex_array_; unsigned int last_output_width_, last_output_height_; void set_timing_uniforms(); void set_colour_space_uniforms(); void set_gamma(); void establish_OpenGL_state(); void reset_all_OpenGL_state(); GLsync fence_; float get_composite_output_width() const; void set_output_shader_width(); bool get_is_television_output(); public: // These two are protected by output_mutex_. TextureBuilder texture_builder; ArrayBuilder array_builder; OpenGLOutputBuilder(size_t bytes_per_pixel); ~OpenGLOutputBuilder(); inline void set_colour_format(ColourSpace colour_space, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator) { std::lock_guard output_guard(output_mutex_); colour_space_ = colour_space; colour_cycle_numerator_ = colour_cycle_numerator; colour_cycle_denominator_ = colour_cycle_denominator; set_colour_space_uniforms(); } inline void set_visible_area(Rect visible_area) { visible_area_ = visible_area; } inline void set_gamma(float gamma) { gamma_ = gamma; set_gamma(); } inline std::unique_lock get_output_lock() { return std::unique_lock(output_mutex_); } inline OutputDevice get_output_device() { return output_device_; } inline uint16_t get_composite_output_y() { return (uint16_t)composite_src_output_y_; } inline bool composite_output_buffer_is_full() { return composite_src_output_y_ == IntermediateBufferHeight; } inline void increment_composite_output_y() { if(!composite_output_buffer_is_full()) composite_src_output_y_++; } 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); void set_composite_sampling_function(const std::string &shader); void set_rgb_sampling_function(const std::string &shader); void set_output_device(OutputDevice output_device); 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); }; } } #endif /* CRTOpenGL_h */