mirror of
https://github.com/TomHarte/CLK.git
synced 2024-10-13 21:24:23 +00:00
Factored out wraparound buffer addressing where it's otherwise going to get really repetitive; need to look at using the same approach for the glTexSubImage2D step at least but that probably means properly encapsulating the buffer builder's state.
This commit is contained in:
parent
8232ed765e
commit
d9a9dffe63
@ -17,30 +17,30 @@ namespace CRT {
|
|||||||
|
|
||||||
// Output vertices are those used to copy from an input buffer — whether it describes data that maps directly to RGB
|
// 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.
|
// or is one of the intermediate buffers that we've used to convert from composite towards RGB.
|
||||||
const size_t OutputVertexOffsetOfPosition = 0;
|
const GLsizei OutputVertexOffsetOfPosition = 0;
|
||||||
const size_t OutputVertexOffsetOfTexCoord = 4;
|
const GLsizei OutputVertexOffsetOfTexCoord = 4;
|
||||||
const size_t OutputVertexOffsetOfTimestamp = 8;
|
const GLsizei OutputVertexOffsetOfTimestamp = 8;
|
||||||
const size_t OutputVertexOffsetOfLateral = 12;
|
const GLsizei OutputVertexOffsetOfLateral = 12;
|
||||||
const size_t OutputVertexOffsetOfFrameID = 13;
|
const GLsizei OutputVertexOffsetOfFrameID = 13;
|
||||||
|
|
||||||
const size_t OutputVertexSize = 16;
|
const GLsizei OutputVertexSize = 16;
|
||||||
|
|
||||||
// Input vertices, used only in composite mode, map from the input buffer to temporary buffer locations; such
|
// 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
|
// remapping occurs to ensure a continous stream of data for each scan, giving correct out-of-bounds behaviour
|
||||||
const size_t SourceVertexOffsetOfInputPosition = 0;
|
const GLsizei SourceVertexOffsetOfInputPosition = 0;
|
||||||
const size_t SourceVertexOffsetOfOutputPosition = 4;
|
const GLsizei SourceVertexOffsetOfOutputPosition = 4;
|
||||||
const size_t SourceVertexOffsetOfPhaseAmplitudeAndAlpha = 8;
|
const GLsizei SourceVertexOffsetOfPhaseAmplitudeAndAlpha = 8;
|
||||||
const size_t SourceVertexOffsetOfPhaseTime = 12;
|
const GLsizei SourceVertexOffsetOfPhaseTime = 12;
|
||||||
|
|
||||||
const size_t SourceVertexSize = 16;
|
const GLsizei SourceVertexSize = 16;
|
||||||
|
|
||||||
// These constants hold the size of the rolling buffer to which the CPU writes
|
// These constants hold the size of the rolling buffer to which the CPU writes
|
||||||
const int InputBufferBuilderWidth = 2048;
|
const GLsizei InputBufferBuilderWidth = 2048;
|
||||||
const int InputBufferBuilderHeight = 1024;
|
const GLsizei InputBufferBuilderHeight = 1024;
|
||||||
|
|
||||||
// This is the size of the intermediate buffers used during composite to RGB conversion
|
// This is the size of the intermediate buffers used during composite to RGB conversion
|
||||||
const int IntermediateBufferWidth = 2048;
|
const GLsizei IntermediateBufferWidth = 2048;
|
||||||
const int IntermediateBufferHeight = 2048;
|
const GLsizei IntermediateBufferHeight = 2048;
|
||||||
|
|
||||||
// Some internal buffer sizes
|
// Some internal buffer sizes
|
||||||
const GLsizeiptr OutputVertexBufferDataSize = 262080; // a multiple of 6 * OutputVertexSize
|
const GLsizeiptr OutputVertexBufferDataSize = 262080; // a multiple of 6 * OutputVertexSize
|
||||||
|
@ -43,12 +43,6 @@ struct CRTInputBufferBuilder {
|
|||||||
{
|
{
|
||||||
_next_write_x_position = 0;
|
_next_write_x_position = 0;
|
||||||
_next_write_y_position = (_next_write_y_position+1)%InputBufferBuilderHeight;
|
_next_write_y_position = (_next_write_y_position+1)%InputBufferBuilderHeight;
|
||||||
// if(!_next_write_y_position)
|
|
||||||
// {
|
|
||||||
// glClientWaitSync(_wraparound_sync, 0, ~(GLuint64)0);
|
|
||||||
// glDeleteSync(_wraparound_sync);
|
|
||||||
// _wraparound_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t *get_write_target(uint8_t *buffer)
|
inline uint8_t *get_write_target(uint8_t *buffer)
|
||||||
|
@ -36,6 +36,34 @@ static const GLenum formatForDepth(size_t depth)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int getCircularRanges(GLsizei start, GLsizei end, GLsizei buffer_length, GLsizei *ranges)
|
||||||
|
{
|
||||||
|
GLsizei length = end - start;
|
||||||
|
if(!length) return 0;
|
||||||
|
if(length > buffer_length)
|
||||||
|
{
|
||||||
|
ranges[0] = 0;
|
||||||
|
ranges[1] = buffer_length;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ranges[0] = start % buffer_length;
|
||||||
|
if(ranges[0]+length < buffer_length)
|
||||||
|
{
|
||||||
|
ranges[1] = length;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ranges[1] = buffer_length - ranges[0];
|
||||||
|
ranges[2] = 0;
|
||||||
|
ranges[3] = length - ranges[1];
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using namespace Outputs::CRT;
|
using namespace Outputs::CRT;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -207,38 +235,14 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
|
|||||||
if(_drawn_source_buffer_data_pointer != _source_buffer_data_pointer)
|
if(_drawn_source_buffer_data_pointer != _source_buffer_data_pointer)
|
||||||
{
|
{
|
||||||
// determine how many lines are newly reclaimed; they'll need to be cleared
|
// determine how many lines are newly reclaimed; they'll need to be cleared
|
||||||
uint16_t clearing_zones[4];
|
GLsizei clearing_zones[4], drawing_zones[4];
|
||||||
int number_of_clearing_zones = 0;
|
int number_of_clearing_zones = getCircularRanges(_cleared_composite_output_y+1, _composite_src_output_y+1, IntermediateBufferHeight, clearing_zones);
|
||||||
|
int number_of_drawing_zones = getCircularRanges(_drawn_source_buffer_data_pointer, _source_buffer_data_pointer, SourceVertexBufferDataSize, drawing_zones);
|
||||||
|
|
||||||
if(_composite_src_output_y != _cleared_composite_output_y)
|
_composite_src_output_y %= IntermediateBufferHeight;
|
||||||
{
|
_cleared_composite_output_y = _composite_src_output_y;
|
||||||
uint16_t lines_to_clear = _composite_src_output_y - _cleared_composite_output_y;
|
_source_buffer_data_pointer %= SourceVertexBufferDataSize;
|
||||||
if(lines_to_clear > IntermediateBufferHeight)
|
_drawn_source_buffer_data_pointer = _source_buffer_data_pointer;
|
||||||
{
|
|
||||||
number_of_clearing_zones = 1;
|
|
||||||
clearing_zones[0] = 0;
|
|
||||||
clearing_zones[1] = IntermediateBufferHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clearing_zones[0] = (_cleared_composite_output_y+1)%IntermediateBufferHeight;
|
|
||||||
if(clearing_zones[0]+lines_to_clear < IntermediateBufferHeight)
|
|
||||||
{
|
|
||||||
clearing_zones[1] = lines_to_clear;
|
|
||||||
number_of_clearing_zones = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clearing_zones[1] = IntermediateBufferHeight - clearing_zones[0];
|
|
||||||
clearing_zones[2] = 0;
|
|
||||||
clearing_zones[3] = lines_to_clear - clearing_zones[1];
|
|
||||||
number_of_clearing_zones = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_composite_src_output_y %= IntermediateBufferHeight;
|
|
||||||
_cleared_composite_output_y = _composite_src_output_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// all drawing will be from the source vertex array and without blending
|
// all drawing will be from the source vertex array and without blending
|
||||||
glBindVertexArray(source_vertex_array);
|
glBindVertexArray(source_vertex_array);
|
||||||
@ -260,22 +264,10 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
|
|||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t new_data_size = _source_buffer_data_pointer - _drawn_source_buffer_data_pointer;
|
// draw as desired
|
||||||
size_t new_data_start = _drawn_source_buffer_data_pointer;
|
for(int c = 0; c < number_of_drawing_zones; c++)
|
||||||
_source_buffer_data_pointer %= SourceVertexBufferDataSize;
|
|
||||||
_drawn_source_buffer_data_pointer = _source_buffer_data_pointer;
|
|
||||||
|
|
||||||
if(new_data_size >= SourceVertexBufferDataSize)
|
|
||||||
{
|
{
|
||||||
new_data_size = SourceVertexBufferDataSize;
|
glDrawArrays(GL_LINES, drawing_zones[c*2] / SourceVertexSize, drawing_zones[c*2 + 1] / SourceVertexSize);
|
||||||
new_data_start = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t first_data_length = std::min(SourceVertexBufferDataSize - new_data_start, new_data_size);
|
|
||||||
glDrawArrays(GL_LINES, (GLint)(new_data_start / SourceVertexSize), (GLsizei)(first_data_length / SourceVertexSize));
|
|
||||||
if(new_data_size > first_data_length)
|
|
||||||
{
|
|
||||||
glDrawArrays(GL_LINES, 0, (GLsizei)((new_data_size - first_data_length) / SourceVertexSize));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch back to screen output
|
// switch back to screen output
|
||||||
|
@ -126,9 +126,9 @@ class OpenGLOutputBuilder {
|
|||||||
return &_output_buffer_data[_output_buffer_data_pointer];
|
return &_output_buffer_data[_output_buffer_data_pointer];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void complete_output_run(size_t vertices_written)
|
inline void complete_output_run(GLsizei vertices_written)
|
||||||
{
|
{
|
||||||
_run_builders[_run_write_pointer]->amount_of_data += vertices_written * OutputVertexSize;
|
_run_builders[_run_write_pointer]->amount_of_data += (size_t)(vertices_written * OutputVertexSize);
|
||||||
_output_buffer_data_pointer = (_output_buffer_data_pointer + vertices_written * OutputVertexSize) % OutputVertexBufferDataSize;
|
_output_buffer_data_pointer = (_output_buffer_data_pointer + vertices_written * OutputVertexSize) % OutputVertexBufferDataSize;
|
||||||
_output_mutex->unlock();
|
_output_mutex->unlock();
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ class OpenGLOutputBuilder {
|
|||||||
{
|
{
|
||||||
_output_mutex->lock();
|
_output_mutex->lock();
|
||||||
_run_write_pointer = (_run_write_pointer + 1)%NumberOfFields;
|
_run_write_pointer = (_run_write_pointer + 1)%NumberOfFields;
|
||||||
_run_builders[_run_write_pointer]->start = _output_buffer_data_pointer;
|
_run_builders[_run_write_pointer]->start = (size_t)_output_buffer_data_pointer;
|
||||||
_run_builders[_run_write_pointer]->reset();
|
_run_builders[_run_write_pointer]->reset();
|
||||||
_output_mutex->unlock();
|
_output_mutex->unlock();
|
||||||
}
|
}
|
||||||
@ -218,11 +218,11 @@ class OpenGLOutputBuilder {
|
|||||||
GLsizeiptr _input_texture_array_size;
|
GLsizeiptr _input_texture_array_size;
|
||||||
|
|
||||||
uint8_t *_output_buffer_data;
|
uint8_t *_output_buffer_data;
|
||||||
size_t _output_buffer_data_pointer;
|
GLsizei _output_buffer_data_pointer;
|
||||||
|
|
||||||
uint8_t *_source_buffer_data;
|
uint8_t *_source_buffer_data;
|
||||||
size_t _source_buffer_data_pointer;
|
GLsizei _source_buffer_data_pointer;
|
||||||
size_t _drawn_source_buffer_data_pointer;
|
GLsizei _drawn_source_buffer_data_pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user