diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 9005bc3da..7ac235056 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -66,7 +66,7 @@ void Machine::setup_output(float aspect_ratio) "texValue >>= 4 - (int(icoordinate.x * 8) & 4);" "return vec3( uvec3(texValue) & uvec3(4u, 2u, 1u));" "}"); - _crt->set_output_device(Outputs::CRT::Monitor); + _crt->set_output_device(Outputs::CRT::Television); // TODO: as implied below, I've introduced a clock's latency into the graphics pipeline somehow. Investigate. _crt->set_visible_area(_crt->get_rect_for_area(first_graphics_line - 3, 256, (first_graphics_cycle+1) * crt_cycles_multiplier, 80 * crt_cycles_multiplier, 4.0f / 3.0f)); diff --git a/Outputs/CRT/Internals/CRTConstants.hpp b/Outputs/CRT/Internals/CRTConstants.hpp index b2f6b9c69..c42a7fbb9 100644 --- a/Outputs/CRT/Internals/CRTConstants.hpp +++ b/Outputs/CRT/Internals/CRTConstants.hpp @@ -44,7 +44,7 @@ const int IntermediateBufferHeight = 2048; // Some internal buffer sizes const GLsizeiptr OutputVertexBufferDataSize = 262080; // a multiple of 6 * OutputVertexSize -const GLsizeiptr SourceVertexBufferDataSize = 87360; // a multiple of 2 * OutputVertexSize +const GLsizeiptr SourceVertexBufferDataSize = 87360; // a multiple of 2 * SourceVertexSize // Runs are divided discretely by vertical syncs in order to put a usable bounds on the uniform used to track diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index 73318df59..554d10f75 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -53,7 +53,8 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) : _output_buffer_data(nullptr), _source_buffer_data(nullptr), _input_texture_data(nullptr), - _output_buffer_data_pointer(0) + _output_buffer_data_pointer(0), + _source_buffer_data_pointer(0) { _run_builders = new CRTRunBuilder *[NumberOfFields]; for(int builder = 0; builder < NumberOfFields; builder++) @@ -211,7 +212,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out // Ensure we're back on the output framebuffer, drawing from the output array buffer glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer); -// glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); + glBindVertexArray(output_vertex_array); // clear the buffer glClear(GL_COLOR_BUFFER_BIT); @@ -254,7 +255,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); _source_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, SourceVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); - _source_buffer_data_pointer = 0; _input_texture_data = (uint8_t *)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, _input_texture_array_size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); @@ -310,14 +310,18 @@ char *OpenGLOutputBuilder::get_input_vertex_shader() "in float phaseTime;" "uniform float phaseCyclesPerTick;" + "uniform usampler2D texID;" + "uniform ivec2 outputTextureSize;" "out vec2 inputPositionVarying;" "out float phaseVarying;" "void main(void)" "{" - "inputPositionVarying = vec2(inputPositionVarying.x / inputTextureSize.x, (inputPositionVarying.y + 0.5) / inputTextureSize.y);" - "gl_Position = vec4(outputPosition.x * 2.0 / outputTextureSize - 1.0, outputPosition.y * 2.0 / outputTextureSize - 1.0, 0.0, 1.0);" + "ivec2 textureSize = textureSize(texID, 0);" + "inputPositionVarying = vec2(inputPositionVarying.x / textureSize.x, (inputPositionVarying.y + 0.5) / textureSize.y);" + + "gl_Position = vec4(outputPosition / outputTextureSize, 0.0, 1.0);" "phaseVarying = (phaseCyclesPerTick * phaseTime + phaseAndAmplitude.x) * 2.0 * 3.141592654;" "}"); } @@ -327,6 +331,7 @@ char *OpenGLOutputBuilder::get_input_fragment_shader() const char *composite_shader = _composite_shader; if(!composite_shader) { + composite_shader = _rgb_shader; // TODO: synthesise an RGB -> (selected colour space) shader } @@ -344,7 +349,7 @@ char *OpenGLOutputBuilder::get_input_fragment_shader() "void main(void)" "{" - "fragColour = vec4(composite_sample(inputPositionVarying, phaseVarying), 0.0, 0.0, 1.0);" + "fragColour = vec4(rgb_sample(texID, inputPositionVarying, inputPositionVarying), 1.0);" // composite "}" , composite_shader); } @@ -470,9 +475,12 @@ void OpenGLOutputBuilder::prepare_composite_input_shader() GLint texIDUniform = composite_input_shader_program->get_uniform_location("texID"); GLint phaseCyclesPerTickUniform = composite_input_shader_program->get_uniform_location("phaseCyclesPerTick"); + GLint outputTextureSizeUniform = composite_input_shader_program->get_uniform_location("outputTextureSize"); + composite_input_shader_program->bind(); glUniform1i(texIDUniform, first_supplied_buffer_texture_unit); glUniform1f(phaseCyclesPerTickUniform, (float)_colour_cycle_numerator / (float)(_colour_cycle_denominator * _cycles_per_line)); + glUniform2i(outputTextureSizeUniform, IntermediateBufferWidth, IntermediateBufferHeight); } free(vertex_shader); free(fragment_shader); diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index 4407b3e00..9e92675bd 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -112,7 +112,7 @@ class OpenGLOutputBuilder { inline void complete_source_run() { - _source_buffer_data_pointer += 2 * SourceVertexSize; + _source_buffer_data_pointer = (_source_buffer_data_pointer + 2 * SourceVertexSize) % SourceVertexBufferDataSize; _output_mutex->unlock(); }