1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +00:00

Switched to triangle strips, to eliminate the need for any temporary storage for the composite output path.

This commit is contained in:
Thomas Harte 2016-03-05 20:47:11 -05:00
parent 23c223e2ed
commit 3f39803d32
4 changed files with 45 additions and 31 deletions

View File

@ -66,9 +66,9 @@ void CRT::allocate_buffers(unsigned int number, va_list sizes)
_run_builders = new CRTRunBuilder *[kCRTNumberOfFields];
for(int builder = 0; builder < kCRTNumberOfFields; builder++)
{
_run_builders[builder] = new CRTRunBuilder(kCRTOutputVertexSize, 6);
_run_builders[builder] = new CRTRunBuilder(kCRTOutputVertexSize);
}
_composite_src_runs = std::unique_ptr<CRTRunBuilder>(new CRTRunBuilder(kCRTInputVertexSize, 2));
_composite_src_runs = std::unique_ptr<CRTRunBuilder>(new CRTRunBuilder(kCRTInputVertexSize));
va_list va;
va_copy(va, sizes);
@ -84,7 +84,8 @@ CRT::CRT(unsigned int common_output_divisor) :
_visible_area(Rect(0, 0, 1, 1)),
_sync_period(0),
_common_output_divisor(common_output_divisor),
_composite_src_output_y(0)
_composite_src_output_y(0),
_is_writing_composite_run(false)
{
construct_openGL();
}
@ -170,28 +171,28 @@ 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() : _composite_src_runs->get_next_run();
next_run = (_output_device == CRT::Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2);
}
// Vertex output is arranged as:
// Vertex output is arranged for triangle strips, as:
//
// [0/4] 3
// 2 [4/5]
//
// 1 [2/5]
// [0/1] 3
if(next_run)
{
if(_output_device == CRT::Monitor)
{
// set the type, initial raster position and type of this run
output_position_x(0) = output_position_x(1) = output_position_x(4) = (uint16_t)_horizontal_flywheel->get_current_output_position();
output_position_y(0) = output_position_y(1) = output_position_y(4) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
output_timestamp(0) = output_timestamp(1) = output_timestamp(4) = _run_builders[_run_write_pointer]->duration;
output_tex_x(0) = output_tex_x(1) = output_tex_x(4) = tex_x;
output_position_x(0) = output_position_x(1) = output_position_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position();
output_position_y(0) = output_position_y(1) = output_position_y(2) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
output_timestamp(0) = output_timestamp(1) = output_timestamp(2) = _run_builders[_run_write_pointer]->duration;
output_tex_x(0) = output_tex_x(1) = output_tex_x(2) = tex_x;
// these things are constants across the line so just throw them out now
output_tex_y(0) = output_tex_y(4) = output_tex_y(1) = output_tex_y(2) = output_tex_y(3) = output_tex_y(5) = tex_y;
output_lateral(0) = output_lateral(4) = output_lateral(5) = 0;
output_lateral(1) = output_lateral(2) = output_lateral(3) = 1;
output_tex_y(0) = output_tex_y(1) = output_tex_y(2) = output_tex_y(3) = output_tex_y(4) = output_tex_y(5) = tex_y;
output_lateral(0) = output_lateral(1) = output_lateral(3) = 0;
output_lateral(2) = output_lateral(4) = output_lateral(5) = 1;
}
else
{
@ -228,10 +229,10 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
if(_output_device == CRT::Monitor)
{
// store the final raster position
output_position_x(2) = output_position_x(3) = output_position_x(5) = (uint16_t)_horizontal_flywheel->get_current_output_position();
output_position_y(2) = output_position_y(3) = output_position_y(5) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
output_timestamp(2) = output_timestamp(3) = output_timestamp(5) = _run_builders[_run_write_pointer]->duration;
output_tex_x(2) = output_tex_x(3) = output_tex_x(5) = tex_x;
output_position_x(3) = output_position_x(4) = output_position_x(5) = (uint16_t)_horizontal_flywheel->get_current_output_position();
output_position_y(3) = output_position_y(4) = output_position_y(5) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
output_timestamp(3) = output_timestamp(4) = output_timestamp(5) = _run_builders[_run_write_pointer]->duration;
output_tex_x(3) = output_tex_x(4) = output_tex_x(5) = tex_x;
}
else
{
@ -291,6 +292,19 @@ void CRT::output_scan(Scan *scan)
bool vsync_requested = is_trailing_edge && (_sync_capacitor_charge_level >= _sync_capacitor_charge_threshold);
_is_receiving_sync = this_is_sync;
// simplified colour burst logic: if it's within the back porch we'll take it
if(scan->type == Type::ColourBurst)
{
if(_horizontal_flywheel->get_current_time() < (_horizontal_flywheel->get_standard_period() * 12) >> 6)
{
_colour_burst_time = (uint16_t)_colour_burst_time;
_colour_burst_phase = scan->phase;
_colour_burst_amplitude = scan->amplitude;
}
}
// TODO: inspect raw data for potential colour burst if required
_sync_period = _is_receiving_sync ? (_sync_period + scan->number_of_cycles) : 0;
advance_cycles(scan->number_of_cycles, scan->source_divider, hsync_requested, vsync_requested, this_is_sync, scan->type, scan->tex_x, scan->tex_y);
}
@ -327,13 +341,13 @@ void CRT::output_level(unsigned int number_of_cycles)
output_scan(&scan);
}
void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t magnitude)
void CRT::output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t amplitude)
{
Scan scan {
.type = Type::ColourBurst,
.number_of_cycles = number_of_cycles,
.phase = phase,
.magnitude = magnitude
.amplitude = amplitude
};
output_scan(&scan);
}

View File

@ -141,10 +141,10 @@ class CRT {
@param phase The initial phase of the colour burst in a measuring system with 256 units
per circle, e.g. 0 = 0 degrees, 128 = 180 degrees, 256 = 360 degree.
@param magnitude The magnitude of the colour burst in 1/256ths of the magnitude of the
@param amplitude The amplitude of the colour burst in 1/256ths of the amplitude of the
positive portion of the wave.
*/
void output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t magnitude);
void output_colour_burst(unsigned int number_of_cycles, uint8_t phase, uint8_t amplitude);
/*! Ensures that the given number of output samples are allocated for writing.
@ -289,14 +289,14 @@ class CRT {
uint16_t tex_x, tex_y;
};
struct {
uint8_t phase, magnitude;
uint8_t phase, amplitude;
};
};
};
void output_scan(Scan *scan);
struct CRTRunBuilder {
CRTRunBuilder(size_t vertex_size, int vertices_per_run) : _vertex_size(vertex_size), _vertices_per_run(vertices_per_run) { reset(); }
CRTRunBuilder(size_t vertex_size) : _vertex_size(vertex_size) { reset(); }
// Resets the run builder.
void reset();
@ -305,7 +305,7 @@ class CRT {
// 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();
uint8_t *get_next_run(size_t number_of_vertices);
std::vector<uint8_t> _runs;
// Container for total length in cycles of all contained runs.
@ -318,7 +318,6 @@ class CRT {
private:
size_t _vertex_size;
int _vertices_per_run;
};
struct CRTInputBufferBuilder {
@ -358,6 +357,7 @@ class CRT {
uint16_t _composite_src_output_y;
uint8_t _colour_burst_phase, _colour_burst_amplitude;
uint16_t _colour_burst_time;
bool _is_writing_composite_run;
// OpenGL state, kept behind an opaque pointer to avoid inclusion of the GL headers here.
struct OpenGLState;

View File

@ -86,16 +86,16 @@ void CRT::CRTRunBuilder::reset()
duration = 0;
}
uint8_t *CRT::CRTRunBuilder::get_next_run()
uint8_t *CRT::CRTRunBuilder::get_next_run(size_t number_of_vertices_in_run)
{
// get a run from the allocated list, allocating more if we're about to overrun
if((number_of_vertices + (size_t)_vertices_per_run) * _vertex_size >= _runs.size())
if((number_of_vertices + number_of_vertices_in_run) * _vertex_size >= _runs.size())
{
_runs.resize(_runs.size() + _vertex_size * (size_t)_vertices_per_run * 100);
_runs.resize(_runs.size() + _vertex_size * 100);
}
uint8_t *next_run = &_runs[number_of_vertices * _vertex_size];
number_of_vertices += (size_t)_vertices_per_run;
number_of_vertices += number_of_vertices_in_run;
return next_run;
}

View File

@ -172,7 +172,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
}
// draw this frame
glDrawArrays(GL_TRIANGLES, (GLint)(run * _openGL_state->verticesPerSlice), (GLsizei)_run_builders[run]->number_of_vertices);
glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(run * _openGL_state->verticesPerSlice), (GLsizei)_run_builders[run]->number_of_vertices);
}
// advance back in time