mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Switched to triangle strips, to eliminate the need for any temporary storage for the composite output path.
This commit is contained in:
parent
23c223e2ed
commit
3f39803d32
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user