1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +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:
Thomas Harte 2016-04-20 21:05:32 -04:00
parent 8232ed765e
commit d9a9dffe63
4 changed files with 59 additions and 73 deletions

View File

@ -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
// or is one of the intermediate buffers that we've used to convert from composite towards RGB.
const size_t OutputVertexOffsetOfPosition = 0;
const size_t OutputVertexOffsetOfTexCoord = 4;
const size_t OutputVertexOffsetOfTimestamp = 8;
const size_t OutputVertexOffsetOfLateral = 12;
const size_t OutputVertexOffsetOfFrameID = 13;
const GLsizei OutputVertexOffsetOfPosition = 0;
const GLsizei OutputVertexOffsetOfTexCoord = 4;
const GLsizei OutputVertexOffsetOfTimestamp = 8;
const GLsizei OutputVertexOffsetOfLateral = 12;
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
// remapping occurs to ensure a continous stream of data for each scan, giving correct out-of-bounds behaviour
const size_t SourceVertexOffsetOfInputPosition = 0;
const size_t SourceVertexOffsetOfOutputPosition = 4;
const size_t SourceVertexOffsetOfPhaseAmplitudeAndAlpha = 8;
const size_t SourceVertexOffsetOfPhaseTime = 12;
const GLsizei SourceVertexOffsetOfInputPosition = 0;
const GLsizei SourceVertexOffsetOfOutputPosition = 4;
const GLsizei SourceVertexOffsetOfPhaseAmplitudeAndAlpha = 8;
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
const int InputBufferBuilderWidth = 2048;
const int InputBufferBuilderHeight = 1024;
const GLsizei InputBufferBuilderWidth = 2048;
const GLsizei InputBufferBuilderHeight = 1024;
// This is the size of the intermediate buffers used during composite to RGB conversion
const int IntermediateBufferWidth = 2048;
const int IntermediateBufferHeight = 2048;
const GLsizei IntermediateBufferWidth = 2048;
const GLsizei IntermediateBufferHeight = 2048;
// Some internal buffer sizes
const GLsizeiptr OutputVertexBufferDataSize = 262080; // a multiple of 6 * OutputVertexSize

View File

@ -43,12 +43,6 @@ struct CRTInputBufferBuilder {
{
_next_write_x_position = 0;
_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)

View File

@ -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;
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)
{
// determine how many lines are newly reclaimed; they'll need to be cleared
uint16_t clearing_zones[4];
int number_of_clearing_zones = 0;
GLsizei clearing_zones[4], drawing_zones[4];
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)
{
uint16_t lines_to_clear = _composite_src_output_y - _cleared_composite_output_y;
if(lines_to_clear > IntermediateBufferHeight)
{
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;
}
_composite_src_output_y %= IntermediateBufferHeight;
_cleared_composite_output_y = _composite_src_output_y;
_source_buffer_data_pointer %= SourceVertexBufferDataSize;
_drawn_source_buffer_data_pointer = _source_buffer_data_pointer;
// all drawing will be from the source vertex array and without blending
glBindVertexArray(source_vertex_array);
@ -260,22 +264,10 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
glDisable(GL_SCISSOR_TEST);
}
size_t new_data_size = _source_buffer_data_pointer - _drawn_source_buffer_data_pointer;
size_t new_data_start = _drawn_source_buffer_data_pointer;
_source_buffer_data_pointer %= SourceVertexBufferDataSize;
_drawn_source_buffer_data_pointer = _source_buffer_data_pointer;
if(new_data_size >= SourceVertexBufferDataSize)
// draw as desired
for(int c = 0; c < number_of_drawing_zones; c++)
{
new_data_size = SourceVertexBufferDataSize;
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));
glDrawArrays(GL_LINES, drawing_zones[c*2] / SourceVertexSize, drawing_zones[c*2 + 1] / SourceVertexSize);
}
// switch back to screen output

View File

@ -126,9 +126,9 @@ class OpenGLOutputBuilder {
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_mutex->unlock();
}
@ -162,7 +162,7 @@ class OpenGLOutputBuilder {
{
_output_mutex->lock();
_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();
_output_mutex->unlock();
}
@ -218,11 +218,11 @@ class OpenGLOutputBuilder {
GLsizeiptr _input_texture_array_size;
uint8_t *_output_buffer_data;
size_t _output_buffer_data_pointer;
GLsizei _output_buffer_data_pointer;
uint8_t *_source_buffer_data;
size_t _source_buffer_data_pointer;
size_t _drawn_source_buffer_data_pointer;
GLsizei _source_buffer_data_pointer;
GLsizei _drawn_source_buffer_data_pointer;
};
}