diff --git a/Machines/Atari2600/Atari2600.cpp b/Machines/Atari2600/Atari2600.cpp index f76b3033e..2e2e16755 100644 --- a/Machines/Atari2600/Atari2600.cpp +++ b/Machines/Atari2600/Atari2600.cpp @@ -24,7 +24,7 @@ Machine::Machine() : _piaDataValue{0xff, 0xff}, _tiaInputValue{0xff, 0xff} { - _crt = new Outputs::CRT(228, 1, Outputs::CRT::DisplayType::NTSC60, 1, 2); + _crt = new Outputs::CRT::CRT(228, 1, Outputs::CRT::DisplayType::NTSC60, 1, 2); _crt->set_composite_sampling_function( "float composite_sample(vec2 coordinate, float phase)\n" "{\n" diff --git a/Machines/Atari2600/Atari2600.hpp b/Machines/Atari2600/Atari2600.hpp index 8c77f8605..c3b5d6209 100644 --- a/Machines/Atari2600/Atari2600.hpp +++ b/Machines/Atari2600/Atari2600.hpp @@ -29,7 +29,7 @@ class Machine: public CPU6502::Processor { void set_digital_input(Atari2600DigitalInput input, bool state); - Outputs::CRT *get_crt() { return _crt; } + Outputs::CRT::CRT *get_crt() { return _crt; } private: uint8_t *_rom, *_romPages[4], _ram[128]; @@ -90,7 +90,7 @@ class Machine: public CPU6502::Processor { void output_pixels(unsigned int count); void get_output_pixel(uint8_t *pixel, int offset); - Outputs::CRT *_crt; + Outputs::CRT::CRT *_crt; // latched output state unsigned int _lastOutputStateDuration; diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 5031f594d..90d41a394 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -32,7 +32,7 @@ Machine::Machine() : _audioOutputPositionError(0), _currentOutputLine(0), _is_odd_field(false), - _crt(std::unique_ptr(new Outputs::CRT(crt_cycles_per_line, 8, Outputs::CRT::DisplayType::PAL50, 1, 1))) + _crt(std::unique_ptr(new Outputs::CRT::CRT(crt_cycles_per_line, 8, Outputs::CRT::DisplayType::PAL50, 1, 1))) { _crt->set_rgb_sampling_function( "vec4 rgb_sample(vec2 coordinate)" diff --git a/Machines/Electron/Electron.hpp b/Machines/Electron/Electron.hpp index e9fb3c1d0..75758366c 100644 --- a/Machines/Electron/Electron.hpp +++ b/Machines/Electron/Electron.hpp @@ -147,7 +147,7 @@ class Machine: public CPU6502::Processor, Tape::Delegate { void set_key_state(Key key, bool isPressed); - Outputs::CRT *get_crt() { return _crt.get(); } + Outputs::CRT::CRT *get_crt() { return _crt.get(); } Outputs::Speaker *get_speaker() { return &_speaker; } virtual void tape_did_change_interrupt_status(Tape *tape); @@ -201,7 +201,7 @@ class Machine: public CPU6502::Processor, Tape::Delegate { Tape _tape; // Outputs. - std::unique_ptr _crt; + std::unique_ptr _crt; Speaker _speaker; }; diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 4f524ad3c..733f1da82 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -11,7 +11,7 @@ #include #include -using namespace Outputs; +using namespace Outputs::CRT; void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_display, ColourSpace colour_space, unsigned int colour_cycle_numerator, unsigned int colour_cycle_denominator) { @@ -39,8 +39,8 @@ void CRT::set_new_timing(unsigned int cycles_per_line, unsigned int height_of_di _sync_capacitor_charge_threshold = ((syncCapacityLineChargeThreshold * _cycles_per_line) * 50) >> 7; // create the two flywheels - _horizontal_flywheel = std::unique_ptr(new Outputs::Flywheel(_cycles_per_line, (millisecondsHorizontalRetraceTime * _cycles_per_line) >> 6)); - _vertical_flywheel = std::unique_ptr(new Outputs::Flywheel(_cycles_per_line * height_of_display, scanlinesVerticalRetraceTime * _cycles_per_line)); + _horizontal_flywheel = std::unique_ptr(new Flywheel(_cycles_per_line, (millisecondsHorizontalRetraceTime * _cycles_per_line) >> 6)); + _vertical_flywheel = std::unique_ptr(new Flywheel(_cycles_per_line * height_of_display, scanlinesVerticalRetraceTime * _cycles_per_line)); // figure out the divisor necessary to get the horizontal flywheel into a 16-bit range unsigned int real_clock_scan_period = (_cycles_per_line * height_of_display) / (_time_multiplier * _common_output_divisor); @@ -63,12 +63,12 @@ void CRT::set_new_display_type(unsigned int cycles_per_line, DisplayType display void CRT::allocate_buffers(unsigned int number, va_list sizes) { - _run_builders = new CRTRunBuilder *[kCRTNumberOfFields]; - for(int builder = 0; builder < kCRTNumberOfFields; builder++) + _run_builders = new CRTRunBuilder *[NumberOfFields]; + for(int builder = 0; builder < NumberOfFields; builder++) { - _run_builders[builder] = new CRTRunBuilder(kCRTOutputVertexSize); + _run_builders[builder] = new CRTRunBuilder(OutputVertexSize); } - _composite_src_runs = std::unique_ptr(new CRTRunBuilder(kCRTInputVertexSize)); + _composite_src_runs = std::unique_ptr(new CRTRunBuilder(InputVertexSize)); va_list va; va_copy(va, sizes); @@ -92,7 +92,7 @@ CRT::CRT(unsigned int common_output_divisor) : CRT::~CRT() { - for(int builder = 0; builder < kCRTNumberOfFields; builder++) + for(int builder = 0; builder < NumberOfFields; builder++) { delete _run_builders[builder]; } @@ -132,20 +132,20 @@ Flywheel::SyncEvent CRT::get_next_horizontal_sync_event(bool hsync_is_requested, return _horizontal_flywheel->get_next_event_in_period(hsync_is_requested, cycles_to_run_for, cycles_advanced); } -#define output_position_x(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfPosition + 0]) -#define output_position_y(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfPosition + 2]) -#define output_tex_x(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTexCoord + 0]) -#define output_tex_y(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTexCoord + 2]) -#define output_lateral(v) next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfLateral] -#define output_timestamp(v) (*(uint32_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTimestamp]) +#define output_position_x(v) (*(uint16_t *)&next_run[OutputVertexSize*v + OutputVertexOffsetOfPosition + 0]) +#define output_position_y(v) (*(uint16_t *)&next_run[OutputVertexSize*v + OutputVertexOffsetOfPosition + 2]) +#define output_tex_x(v) (*(uint16_t *)&next_run[OutputVertexSize*v + OutputVertexOffsetOfTexCoord + 0]) +#define output_tex_y(v) (*(uint16_t *)&next_run[OutputVertexSize*v + OutputVertexOffsetOfTexCoord + 2]) +#define output_lateral(v) next_run[OutputVertexSize*v + OutputVertexOffsetOfLateral] +#define output_timestamp(v) (*(uint32_t *)&next_run[OutputVertexSize*v + OutputVertexOffsetOfTimestamp]) -#define input_input_position_x(v) (*(uint16_t *)&next_run[kCRTInputVertexSize*v + kCRTInputVertexOffsetOfInputPosition + 0]) -#define input_input_position_y(v) (*(uint16_t *)&next_run[kCRTInputVertexSize*v + kCRTInputVertexOffsetOfInputPosition + 2]) -#define input_output_position_x(v) (*(uint16_t *)&next_run[kCRTInputVertexSize*v + kCRTInputVertexOffsetOfOutputPosition + 0]) -#define input_output_position_y(v) (*(uint16_t *)&next_run[kCRTInputVertexSize*v + kCRTInputVertexOffsetOfOutputPosition + 2]) -#define input_phase(v) next_run[kCRTOutputVertexSize*v + kCRTInputVertexOffsetOfPhaseAndAmplitude + 0] -#define input_amplitude(v) next_run[kCRTOutputVertexSize*v + kCRTInputVertexOffsetOfPhaseAndAmplitude + 1] -#define input_phase_time(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTInputVertexOffsetOfPhaseTime]) +#define input_input_position_x(v) (*(uint16_t *)&next_run[InputVertexSize*v + InputVertexOffsetOfInputPosition + 0]) +#define input_input_position_y(v) (*(uint16_t *)&next_run[InputVertexSize*v + InputVertexOffsetOfInputPosition + 2]) +#define input_output_position_x(v) (*(uint16_t *)&next_run[InputVertexSize*v + InputVertexOffsetOfOutputPosition + 0]) +#define input_output_position_y(v) (*(uint16_t *)&next_run[InputVertexSize*v + InputVertexOffsetOfOutputPosition + 2]) +#define input_phase(v) next_run[OutputVertexSize*v + InputVertexOffsetOfPhaseAndAmplitude + 0] +#define input_amplitude(v) next_run[OutputVertexSize*v + InputVertexOffsetOfPhaseAndAmplitude + 1] +#define input_phase_time(v) (*(uint16_t *)&next_run[OutputVertexSize*v + InputVertexOffsetOfPhaseTime]) void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divider, bool hsync_requested, bool vsync_requested, const bool vsync_charging, const Type type, uint16_t tex_x, uint16_t tex_y) { @@ -171,7 +171,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi if(is_output_segment) { _output_mutex->lock(); - next_run = (_output_device == CRT::Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2); + next_run = (_output_device == Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2); } // Vertex output is arranged for triangle strips, as: @@ -181,7 +181,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi // [0/1] 3 if(next_run) { - if(_output_device == CRT::Monitor) + if(_output_device == Monitor) { // set the type, initial raster position and type of this run output_position_x(0) = output_position_x(1) = output_position_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position(); @@ -226,7 +226,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi // if this is a data run then advance the buffer pointer if(type == Type::Data && source_divider) tex_x += next_run_length / (_time_multiplier * source_divider); - if(_output_device == CRT::Monitor) + if(_output_device == Monitor) { // store the final raster position output_position_x(3) = output_position_x(4) = output_position_x(5) = (uint16_t)_horizontal_flywheel->get_current_output_position(); @@ -247,7 +247,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi } // if this is horizontal retrace then advance the output line counter and bookend an output run - if(_output_device == CRT::Television) + if(_output_device == Television) { Flywheel::SyncEvent honoured_event = Flywheel::SyncEvent::None; if(next_run_length == time_until_vertical_sync_event && next_vertical_sync_event != Flywheel::SyncEvent::None) honoured_event = next_vertical_sync_event; @@ -274,7 +274,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi if(next_run_length == time_until_horizontal_sync_event && next_horizontal_sync_event == Flywheel::SyncEvent::EndRetrace) { - _composite_src_output_y = (_composite_src_output_y + 1) % CRTIntermediateBufferHeight; + _composite_src_output_y = (_composite_src_output_y + 1) % IntermediateBufferHeight; } } @@ -284,7 +284,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi // TODO: how to communicate did_detect_vsync? Bring the delegate back? // _delegate->crt_did_end_frame(this, &_current_frame_builder->frame, _did_detect_vsync); - _run_write_pointer = (_run_write_pointer + 1)%kCRTNumberOfFields; + _run_write_pointer = (_run_write_pointer + 1)%NumberOfFields; _run_builders[_run_write_pointer]->reset(); } } diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp index a9b7b9ee0..434dc6946 100644 --- a/Outputs/CRT/CRT.hpp +++ b/Outputs/CRT/CRT.hpp @@ -18,6 +18,7 @@ #include "Flywheel.hpp" namespace Outputs { +namespace CRT { struct Rect { struct { @@ -33,25 +34,78 @@ struct Rect { origin({.x = x, .y = y}), size({.width = width, .height =height}) {} }; +enum DisplayType { + PAL50, + NTSC60 +}; + +enum ColourSpace { + YIQ, + YUV +}; + +enum OutputDevice { + Monitor, + Television +}; + +struct CRTInputBufferBuilder { + CRTInputBufferBuilder(unsigned int number_of_buffers, va_list buffer_sizes); + ~CRTInputBufferBuilder(); + + void allocate_write_area(size_t required_length); + void reduce_previous_allocation_to(size_t actual_length); + uint8_t *get_write_target_for_buffer(int buffer); + + // a pointer to the section of content buffer currently being + // returned and to where the next section will begin + uint16_t _next_write_x_position, _next_write_y_position; + uint16_t _write_x_position, _write_y_position; + size_t _write_target_pointer; + size_t _last_allocation_amount; + + struct Buffer { + uint8_t *data; + size_t bytes_per_pixel; + } *buffers; + unsigned int number_of_buffers; + + // Storage for the amount of buffer uploaded so far; initialised correctly by the buffer + // builder but otherwise entrusted to the CRT to update. + unsigned int last_uploaded_line; +}; + +struct CRTRunBuilder { + CRTRunBuilder(size_t vertex_size) : _vertex_size(vertex_size) { reset(); } + + // Resets the run builder. + void reset(); + + // Getter for new storage plus backing storage; in RGB mode input runs will map directly + // from the input buffer to the screen. In composite mode input runs will map from the + // input buffer to the processing buffer, and output runs will map from the processing + // buffer to the screen. + uint8_t *get_next_run(size_t number_of_vertices); + std::vector _runs; + + // Container for total length in cycles of all contained runs. + uint32_t duration; + + // Storage for the length of run data uploaded so far; reset to zero by reset but otherwise + // entrusted to the CRT to update. + size_t uploaded_vertices; + size_t number_of_vertices; + + private: + size_t _vertex_size; +}; + +struct OpenGLState; + class CRT { public: ~CRT(); - enum DisplayType { - PAL50, - NTSC60 - }; - - enum ColourSpace { - YIQ, - YUV - }; - - enum OutputDevice { - Monitor, - Television - }; - /*! Constructs the CRT with a specified clock rate, height and colour subcarrier frequency. The requested number of buffers, each with the requested number of bytes per pixel, is created for the machine to write raw pixel data to. @@ -259,7 +313,7 @@ class CRT { Rect _visible_area; // the two flywheels regulating scanning - std::unique_ptr _horizontal_flywheel, _vertical_flywheel; + std::unique_ptr _horizontal_flywheel, _vertical_flywheel; uint16_t _vertical_flywheel_output_divider; // elements of sync separation @@ -295,57 +349,6 @@ class CRT { }; void output_scan(Scan *scan); - struct CRTRunBuilder { - CRTRunBuilder(size_t vertex_size) : _vertex_size(vertex_size) { reset(); } - - // Resets the run builder. - void reset(); - - // Getter for new storage plus backing storage; in RGB mode input runs will map directly - // from the input buffer to the screen. In composite mode input runs will map from the - // input buffer to the processing buffer, and output runs will map from the processing - // buffer to the screen. - uint8_t *get_next_run(size_t number_of_vertices); - std::vector _runs; - - // Container for total length in cycles of all contained runs. - uint32_t duration; - - // Storage for the length of run data uploaded so far; reset to zero by reset but otherwise - // entrusted to the CRT to update. - size_t uploaded_vertices; - size_t number_of_vertices; - - private: - size_t _vertex_size; - }; - - struct CRTInputBufferBuilder { - CRTInputBufferBuilder(unsigned int number_of_buffers, va_list buffer_sizes); - ~CRTInputBufferBuilder(); - - void allocate_write_area(size_t required_length); - void reduce_previous_allocation_to(size_t actual_length); - uint8_t *get_write_target_for_buffer(int buffer); - - // a pointer to the section of content buffer currently being - // returned and to where the next section will begin - uint16_t _next_write_x_position, _next_write_y_position; - uint16_t _write_x_position, _write_y_position; - size_t _write_target_pointer; - size_t _last_allocation_amount; - - struct Buffer { - uint8_t *data; - size_t bytes_per_pixel; - } *buffers; - unsigned int number_of_buffers; - - // Storage for the amount of buffer uploaded so far; initialised correctly by the buffer - // builder but otherwise entrusted to the CRT to update. - unsigned int last_uploaded_line; - }; - // the run and input data buffers std::unique_ptr _buffer_builder; CRTRunBuilder **_run_builders; @@ -360,7 +363,6 @@ class CRT { bool _is_writing_composite_run; // OpenGL state, kept behind an opaque pointer to avoid inclusion of the GL headers here. - struct OpenGLState; OpenGLState *_openGL_state; // Other things the caller may have provided. @@ -390,6 +392,6 @@ class CRT { }; } - +} #endif /* CRT_cpp */ diff --git a/Outputs/CRT/CRTBuilders.cpp b/Outputs/CRT/CRTBuilders.cpp index bf4eee8bc..342e3e963 100644 --- a/Outputs/CRT/CRTBuilders.cpp +++ b/Outputs/CRT/CRTBuilders.cpp @@ -23,7 +23,7 @@ CRT::CRTInputBufferBuilder::CRTInputBufferBuilder(unsigned int number_of_buffers for(int buffer = 0; buffer < number_of_buffers; buffer++) { buffers[buffer].bytes_per_pixel = va_arg(buffer_sizes, unsigned int); - buffers[buffer].data = new uint8_t[CRTInputBufferBuilderWidth * CRTInputBufferBuilderHeight * buffers[buffer].bytes_per_pixel]; + buffers[buffer].data = new uint8_t[InputBufferBuilderWidth * InputBufferBuilderHeight * buffers[buffer].bytes_per_pixel]; } _next_write_x_position = _next_write_y_position = 0; @@ -42,15 +42,15 @@ void CRT::CRTInputBufferBuilder::allocate_write_area(size_t required_length) { _last_allocation_amount = required_length; - if(_next_write_x_position + required_length + 2 > CRTInputBufferBuilderWidth) + if(_next_write_x_position + required_length + 2 > InputBufferBuilderWidth) { _next_write_x_position = 0; - _next_write_y_position = (_next_write_y_position+1)%CRTInputBufferBuilderHeight; + _next_write_y_position = (_next_write_y_position+1)%InputBufferBuilderHeight; } _write_x_position = _next_write_x_position + 1; _write_y_position = _next_write_y_position; - _write_target_pointer = (_write_y_position * CRTInputBufferBuilderWidth) + _write_x_position; + _write_target_pointer = (_write_y_position * InputBufferBuilderWidth) + _write_x_position; _next_write_x_position += required_length + 2; } diff --git a/Outputs/CRT/CRTOpenGL.cpp b/Outputs/CRT/CRTOpenGL.cpp index 728336e98..0b811a199 100644 --- a/Outputs/CRT/CRTOpenGL.cpp +++ b/Outputs/CRT/CRTOpenGL.cpp @@ -14,9 +14,10 @@ #include "Shader.hpp" #include "CRTOpenGL.hpp" -using namespace Outputs; +namespace Outputs { +namespace CRT { -struct CRT::OpenGLState { +struct OpenGLState { std::unique_ptr rgb_shader_program; std::unique_ptr composite_input_shader_program, composite_output_shader_program; @@ -35,6 +36,11 @@ struct CRT::OpenGLState { std::unique_ptr filteredTexture; // receives filtered YIQ or YUV }; +} +} + +using namespace Outputs::CRT; + namespace { static const GLenum first_supplied_buffer_texture_unit = 3; } @@ -84,7 +90,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GLenum format = formatForDepth(_buffer_builder->buffers[buffer].bytes_per_pixel); - glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight, 0, format, GL_UNSIGNED_BYTE, _buffer_builder->buffers[buffer].data); + glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, InputBufferBuilderWidth, InputBufferBuilderHeight, 0, format, GL_UNSIGNED_BYTE, _buffer_builder->buffers[buffer].data); } glGenVertexArrays(1, &_openGL_state->output_vertex_array); @@ -105,11 +111,11 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool // Create intermediate textures and bind to slots 0, 1 and 2 glActiveTexture(GL_TEXTURE0); - _openGL_state->compositeTexture = std::unique_ptr(new OpenGL::TextureTarget(CRTIntermediateBufferWidth, CRTIntermediateBufferHeight)); + _openGL_state->compositeTexture = std::unique_ptr(new OpenGL::TextureTarget(IntermediateBufferWidth, IntermediateBufferHeight)); glActiveTexture(GL_TEXTURE1); - _openGL_state->filteredYTexture = std::unique_ptr(new OpenGL::TextureTarget(CRTIntermediateBufferWidth, CRTIntermediateBufferHeight)); + _openGL_state->filteredYTexture = std::unique_ptr(new OpenGL::TextureTarget(IntermediateBufferWidth, IntermediateBufferHeight)); glActiveTexture(GL_TEXTURE2); - _openGL_state->filteredTexture = std::unique_ptr(new OpenGL::TextureTarget(CRTIntermediateBufferWidth, CRTIntermediateBufferHeight)); + _openGL_state->filteredTexture = std::unique_ptr(new OpenGL::TextureTarget(IntermediateBufferWidth, IntermediateBufferHeight)); } // glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&_openGL_state->defaultFramebuffer); @@ -129,9 +135,9 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (GLint)_buffer_builder->last_uploaded_line, - CRTInputBufferBuilderWidth, (GLint)(CRTInputBufferBuilderHeight - _buffer_builder->last_uploaded_line), + InputBufferBuilderWidth, (GLint)(InputBufferBuilderHeight - _buffer_builder->last_uploaded_line), format, GL_UNSIGNED_BYTE, - &_buffer_builder->buffers[0].data[_buffer_builder->last_uploaded_line * CRTInputBufferBuilderWidth * _buffer_builder->buffers[0].bytes_per_pixel]); + &_buffer_builder->buffers[0].data[_buffer_builder->last_uploaded_line * InputBufferBuilderWidth * _buffer_builder->buffers[0].bytes_per_pixel]); _buffer_builder->last_uploaded_line = 0; } @@ -139,9 +145,9 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (GLint)_buffer_builder->last_uploaded_line, - CRTInputBufferBuilderWidth, (GLint)(1 + _buffer_builder->_next_write_y_position - _buffer_builder->last_uploaded_line), + InputBufferBuilderWidth, (GLint)(1 + _buffer_builder->_next_write_y_position - _buffer_builder->last_uploaded_line), format, GL_UNSIGNED_BYTE, - &_buffer_builder->buffers[0].data[_buffer_builder->last_uploaded_line * CRTInputBufferBuilderWidth * _buffer_builder->buffers[0].bytes_per_pixel]); + &_buffer_builder->buffers[0].data[_buffer_builder->last_uploaded_line * InputBufferBuilderWidth * _buffer_builder->buffers[0].bytes_per_pixel]); _buffer_builder->last_uploaded_line = _buffer_builder->_next_write_y_position; } } @@ -163,19 +169,19 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool // ensure array buffer is up to date glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->output_array_buffer); size_t max_number_of_vertices = 0; - for(int c = 0; c < kCRTNumberOfFields; c++) + for(int c = 0; c < NumberOfFields; c++) { max_number_of_vertices = std::max(max_number_of_vertices, _run_builders[c]->number_of_vertices); } if(_openGL_state->output_vertices_per_slice < max_number_of_vertices) { _openGL_state->output_vertices_per_slice = max_number_of_vertices; - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(max_number_of_vertices * kCRTOutputVertexSize * kCRTOutputVertexSize), NULL, GL_STREAM_DRAW); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(max_number_of_vertices * OutputVertexSize * OutputVertexSize), NULL, GL_STREAM_DRAW); - for(unsigned int c = 0; c < kCRTNumberOfFields; c++) + for(unsigned int c = 0; c < NumberOfFields; c++) { uint8_t *data = &_run_builders[c]->_runs[0]; - glBufferSubData(GL_ARRAY_BUFFER, (GLsizeiptr)(c * _openGL_state->output_vertices_per_slice * kCRTOutputVertexSize), (GLsizeiptr)(_run_builders[c]->number_of_vertices * kCRTOutputVertexSize), data); + glBufferSubData(GL_ARRAY_BUFFER, (GLsizeiptr)(c * _openGL_state->output_vertices_per_slice * OutputVertexSize), (GLsizeiptr)(_run_builders[c]->number_of_vertices * OutputVertexSize), data); _run_builders[c]->uploaded_vertices = _run_builders[c]->number_of_vertices; } } @@ -198,7 +204,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool unsigned int run = (unsigned int)_run_write_pointer; // printf("%d: %zu v %zu\n", run, _run_builders[run]->uploaded_vertices, _run_builders[run]->number_of_vertices); GLint total_age = 0; - for(int c = 0; c < kCRTNumberOfFields; c++) + for(int c = 0; c < NumberOfFields; c++) { // update the total age at the start of this set of runs total_age += _run_builders[run]->duration; @@ -209,10 +215,10 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool if(_run_builders[run]->uploaded_vertices != _run_builders[run]->number_of_vertices) { - uint8_t *data = &_run_builders[run]->_runs[_run_builders[run]->uploaded_vertices * kCRTOutputVertexSize]; + uint8_t *data = &_run_builders[run]->_runs[_run_builders[run]->uploaded_vertices * OutputVertexSize]; glBufferSubData(GL_ARRAY_BUFFER, - (GLsizeiptr)(((run * _openGL_state->output_vertices_per_slice) + _run_builders[run]->uploaded_vertices) * kCRTOutputVertexSize), - (GLsizeiptr)((_run_builders[run]->number_of_vertices - _run_builders[run]->uploaded_vertices) * kCRTOutputVertexSize), data); + (GLsizeiptr)(((run * _openGL_state->output_vertices_per_slice) + _run_builders[run]->uploaded_vertices) * OutputVertexSize), + (GLsizeiptr)((_run_builders[run]->number_of_vertices - _run_builders[run]->uploaded_vertices) * OutputVertexSize), data); _run_builders[run]->uploaded_vertices = _run_builders[run]->number_of_vertices; } @@ -221,7 +227,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool } // advance back in time - run = (run - 1 + kCRTNumberOfFields) % kCRTNumberOfFields; + run = (run - 1 + NumberOfFields) % NumberOfFields; } } @@ -437,8 +443,8 @@ void CRT::prepare_composite_input_shader() GLint phaseCyclesPerTickUniform = _openGL_state->composite_input_shader_program->get_uniform_location("phaseCyclesPerTick"); glUniform1i(texIDUniform, first_supplied_buffer_texture_unit); - glUniform2f(outputTextureSizeUniform, CRTIntermediateBufferWidth, CRTIntermediateBufferHeight); - glUniform2f(inputTextureSizeUniform, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight); + glUniform2f(outputTextureSizeUniform, IntermediateBufferWidth, IntermediateBufferHeight); + glUniform2f(inputTextureSizeUniform, InputBufferBuilderWidth, InputBufferBuilderHeight); glUniform1f(phaseCyclesPerTickUniform, (float)_colour_cycle_numerator / (float)(_colour_cycle_denominator * _cycles_per_line)); } free(vertex_shader); @@ -509,7 +515,7 @@ void CRT::prepare_rgb_output_shader() glUniform1i(texIDUniform, first_supplied_buffer_texture_unit); glUniform1i(shadowMaskTexIDUniform, 1); - glUniform2f(textureSizeUniform, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight); + glUniform2f(textureSizeUniform, InputBufferBuilderWidth, InputBufferBuilderHeight); glUniform1f(ticksPerFrameUniform, (GLfloat)(_cycles_per_line * _height_of_display)); glUniform2f(positionConversionUniform, _horizontal_flywheel->get_scan_period(), _vertical_flywheel->get_scan_period() / (unsigned int)_vertical_flywheel_output_divider); @@ -539,23 +545,23 @@ void CRT::prepare_output_vertex_array() glEnableVertexAttribArray((GLuint)lateralAttribute); glEnableVertexAttribArray((GLuint)timestampAttribute); - const GLsizei vertexStride = kCRTOutputVertexSize; - glVertexAttribPointer((GLuint)positionAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)kCRTOutputVertexOffsetOfPosition); - glVertexAttribPointer((GLuint)textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)kCRTOutputVertexOffsetOfTexCoord); - glVertexAttribPointer((GLuint)timestampAttribute, 4, GL_UNSIGNED_INT, GL_FALSE, vertexStride, (void *)kCRTOutputVertexOffsetOfTimestamp); - glVertexAttribPointer((GLuint)lateralAttribute, 1, GL_UNSIGNED_BYTE, GL_FALSE, vertexStride, (void *)kCRTOutputVertexOffsetOfLateral); + const GLsizei vertexStride = OutputVertexSize; + glVertexAttribPointer((GLuint)positionAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)OutputVertexOffsetOfPosition); + glVertexAttribPointer((GLuint)textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)OutputVertexOffsetOfTexCoord); + glVertexAttribPointer((GLuint)timestampAttribute, 4, GL_UNSIGNED_INT, GL_FALSE, vertexStride, (void *)OutputVertexOffsetOfTimestamp); + glVertexAttribPointer((GLuint)lateralAttribute, 1, GL_UNSIGNED_BYTE, GL_FALSE, vertexStride, (void *)OutputVertexOffsetOfLateral); } } #pragma mark - Configuration -void CRT::set_output_device(CRT::OutputDevice output_device) +void CRT::set_output_device(OutputDevice output_device) { if (_output_device != output_device) { _output_device = output_device; - for(int builder = 0; builder < kCRTNumberOfFields; builder++) + for(int builder = 0; builder < NumberOfFields; builder++) { _run_builders[builder]->reset(); } diff --git a/Outputs/CRT/CRTOpenGL.hpp b/Outputs/CRT/CRTOpenGL.hpp index dd28b5f0d..35e340ca9 100644 --- a/Outputs/CRT/CRTOpenGL.hpp +++ b/Outputs/CRT/CRTOpenGL.hpp @@ -9,35 +9,41 @@ #ifndef CRTOpenGL_h #define CRTOpenGL_h +namespace Outputs { +namespace CRT { + // Output vertices are those used to copy from an input buffer — whether it describes data that maps directly to RGB // or is one of the intermediate buffers that we've used to convert from composite towards RGB. -const size_t kCRTOutputVertexOffsetOfPosition = 0; -const size_t kCRTOutputVertexOffsetOfTexCoord = 4; -const size_t kCRTOutputVertexOffsetOfTimestamp = 8; -const size_t kCRTOutputVertexOffsetOfLateral = 12; +const size_t OutputVertexOffsetOfPosition = 0; +const size_t OutputVertexOffsetOfTexCoord = 4; +const size_t OutputVertexOffsetOfTimestamp = 8; +const size_t OutputVertexOffsetOfLateral = 12; -const size_t kCRTOutputVertexSize = 16; +const size_t OutputVertexSize = 16; // Input vertices, used only in composite mode, map from the input buffer to temporary buffer locations; such // remapping occurs to ensure a continous stream of data for each scan, giving correct out-of-bounds behaviour -const size_t kCRTInputVertexOffsetOfInputPosition = 0; -const size_t kCRTInputVertexOffsetOfOutputPosition = 4; -const size_t kCRTInputVertexOffsetOfPhaseAndAmplitude = 8; -const size_t kCRTInputVertexOffsetOfPhaseTime = 12; +const size_t InputVertexOffsetOfInputPosition = 0; +const size_t InputVertexOffsetOfOutputPosition = 4; +const size_t InputVertexOffsetOfPhaseAndAmplitude = 8; +const size_t InputVertexOffsetOfPhaseTime = 12; -const size_t kCRTInputVertexSize = 16; +const size_t InputVertexSize = 16; // These constants hold the size of the rolling buffer to which the CPU writes -const int CRTInputBufferBuilderWidth = 2048; -const int CRTInputBufferBuilderHeight = 1024; +const int InputBufferBuilderWidth = 2048; +const int InputBufferBuilderHeight = 1024; // This is the size of the intermediate buffers used during composite to RGB conversion -const int CRTIntermediateBufferWidth = 2048; -const int CRTIntermediateBufferHeight = 2048; +const int IntermediateBufferWidth = 2048; +const int IntermediateBufferHeight = 2048; // Runs are divided discretely by vertical syncs in order to put a usable bounds on the uniform used to track // run age; that therefore creates a discrete number of fields that are stored. This number should be the // number of historic fields that are required fully to -const int kCRTNumberOfFields = 3; +const int NumberOfFields = 3; + +} +} #endif /* CRTOpenGL_h */ diff --git a/Outputs/CRT/Flywheel.hpp b/Outputs/CRT/Flywheel.hpp index e72255f1f..e10d621fd 100644 --- a/Outputs/CRT/Flywheel.hpp +++ b/Outputs/CRT/Flywheel.hpp @@ -10,6 +10,7 @@ #define Flywheel_hpp namespace Outputs { +namespace CRT { /*! Provides timing for a two-phase signal consisting of a retrace phase followed by a scan phase, @@ -211,6 +212,7 @@ struct Flywheel */ }; +} } #endif /* Flywheel_hpp */