1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-15 15:29:53 +00:00

Ever more baby steps back towards composite decoding.

This commit is contained in:
Thomas Harte 2016-03-05 14:36:12 -05:00
parent 95efeb1d56
commit 70b6d51451
4 changed files with 64 additions and 33 deletions

View File

@ -63,11 +63,12 @@ void CRT::set_new_display_type(unsigned int cycles_per_line, DisplayType display
void CRT::allocate_buffers(unsigned int number, va_list sizes)
{
_run_builders = new CRTRunBuilder *[kCRTNumberOfFrames];
for(int builder = 0; builder < kCRTNumberOfFrames; builder++)
_run_builders = new CRTRunBuilder *[kCRTNumberOfFields];
for(int builder = 0; builder < kCRTNumberOfFields; builder++)
{
_run_builders[builder] = new CRTRunBuilder(kCRTSizeOfVertex);
_run_builders[builder] = new CRTRunBuilder(kCRTOutputVertexSize);
}
_composite_src_runs = std::unique_ptr<CRTRunBuilder>(new CRTRunBuilder(23));
va_list va;
va_copy(va, sizes);
@ -90,7 +91,7 @@ CRT::CRT(unsigned int common_output_divisor) :
CRT::~CRT()
{
for(int builder = 0; builder < kCRTNumberOfFrames; builder++)
for(int builder = 0; builder < kCRTNumberOfFields; builder++)
{
delete _run_builders[builder];
}
@ -151,12 +152,12 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
uint8_t *next_run = ((is_output_run && next_run_length) && !_horizontal_flywheel->is_in_retrace() && !_vertical_flywheel->is_in_retrace()) ? _run_builders[_run_write_pointer]->get_next_run() : nullptr;
#define position_x(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfPosition + 0])
#define position_y(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfPosition + 2])
#define tex_x(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTexCoord + 0])
#define tex_y(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTexCoord + 2])
#define lateral(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfLateral]
#define timestamp(v) (*(uint32_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTimestamp])
#define position_x(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfPosition + 0])
#define position_y(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfPosition + 2])
#define tex_x(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTexCoord + 0])
#define tex_y(v) (*(uint16_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTexCoord + 2])
#define lateral(v) next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfLateral]
#define timestamp(v) (*(uint32_t *)&next_run[kCRTOutputVertexSize*v + kCRTOutputVertexOffsetOfTimestamp])
// Vertex output is arranged as:
//
@ -212,7 +213,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
// TODO: how to communicate did_detect_vsync? Bring the delegate back?
// _delegate->crt_did_end_frame(this, &_current_frame_builder->frame, _did_detect_vsync);
_run_write_pointer = (_run_write_pointer + 1)%kCRTNumberOfFrames;
_run_write_pointer = (_run_write_pointer + 1)%kCRTNumberOfFields;
_run_builders[_run_write_pointer]->reset();
}
}

View File

@ -353,6 +353,10 @@ class CRT {
int _run_write_pointer;
std::shared_ptr<std::mutex> _output_mutex;
// transient buffers indicating composite data not yet decoded
std::unique_ptr<CRTRunBuilder> _composite_src_runs;
int _composite_src_output_y;
// OpenGL state, kept behind an opaque pointer to avoid inclusion of the GL headers here.
struct OpenGLState;
OpenGLState *_openGL_state;

View File

@ -132,19 +132,19 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
// ensure array buffer is up to date
size_t max_number_of_vertices = 0;
for(int c = 0; c < kCRTNumberOfFrames; c++)
for(int c = 0; c < kCRTNumberOfFields; c++)
{
max_number_of_vertices = std::max(max_number_of_vertices, _run_builders[c]->number_of_vertices);
}
if(_openGL_state->verticesPerSlice < max_number_of_vertices)
{
_openGL_state->verticesPerSlice = max_number_of_vertices;
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(max_number_of_vertices * kCRTSizeOfVertex * kCRTNumberOfFrames), NULL, GL_STREAM_DRAW);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(max_number_of_vertices * kCRTOutputVertexSize * kCRTOutputVertexSize), NULL, GL_STREAM_DRAW);
for(unsigned int c = 0; c < kCRTNumberOfFrames; c++)
for(unsigned int c = 0; c < kCRTNumberOfFields; c++)
{
uint8_t *data = &_run_builders[c]->_runs[0];
glBufferSubData(GL_ARRAY_BUFFER, (GLsizeiptr)(c * _openGL_state->verticesPerSlice * kCRTSizeOfVertex), (GLsizeiptr)(_run_builders[c]->number_of_vertices * kCRTSizeOfVertex), data);
glBufferSubData(GL_ARRAY_BUFFER, (GLsizeiptr)(c * _openGL_state->verticesPerSlice * kCRTOutputVertexSize), (GLsizeiptr)(_run_builders[c]->number_of_vertices * kCRTOutputVertexSize), data);
_run_builders[c]->uploaded_vertices = _run_builders[c]->number_of_vertices;
}
}
@ -153,7 +153,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
unsigned int run = (unsigned int)_run_write_pointer;
// printf("%d: %zu v %zu\n", run, _run_builders[run]->uploaded_vertices, _run_builders[run]->number_of_vertices);
GLint total_age = 0;
for(int c = 0; c < kCRTNumberOfFrames; c++)
for(int c = 0; c < kCRTNumberOfFields; c++)
{
// update the total age at the start of this set of runs
total_age += _run_builders[run]->duration;
@ -164,10 +164,10 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
if(_run_builders[run]->uploaded_vertices != _run_builders[run]->number_of_vertices)
{
uint8_t *data = &_run_builders[run]->_runs[_run_builders[run]->uploaded_vertices * kCRTSizeOfVertex];
uint8_t *data = &_run_builders[run]->_runs[_run_builders[run]->uploaded_vertices * kCRTOutputVertexSize];
glBufferSubData(GL_ARRAY_BUFFER,
(GLsizeiptr)(((run * _openGL_state->verticesPerSlice) + _run_builders[run]->uploaded_vertices) * kCRTSizeOfVertex),
(GLsizeiptr)((_run_builders[run]->number_of_vertices - _run_builders[run]->uploaded_vertices) * kCRTSizeOfVertex), data);
(GLsizeiptr)(((run * _openGL_state->verticesPerSlice) + _run_builders[run]->uploaded_vertices) * kCRTOutputVertexSize),
(GLsizeiptr)((_run_builders[run]->number_of_vertices - _run_builders[run]->uploaded_vertices) * kCRTOutputVertexSize), data);
_run_builders[run]->uploaded_vertices = _run_builders[run]->number_of_vertices;
}
@ -176,7 +176,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
}
// advance back in time
run = (run - 1 + kCRTNumberOfFrames) % kCRTNumberOfFrames;
run = (run - 1 + kCRTNumberOfFields) % kCRTNumberOfFields;
}
_output_mutex->unlock();
@ -389,14 +389,26 @@ void CRT::prepare_vertex_array()
glEnableVertexAttribArray((GLuint)_openGL_state->lateralAttribute);
glEnableVertexAttribArray((GLuint)_openGL_state->timestampAttribute);
const GLsizei vertexStride = kCRTSizeOfVertex;
glVertexAttribPointer((GLuint)_openGL_state->positionAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)kCRTVertexOffsetOfPosition);
glVertexAttribPointer((GLuint)_openGL_state->textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)kCRTVertexOffsetOfTexCoord);
glVertexAttribPointer((GLuint)_openGL_state->timestampAttribute, 4, GL_UNSIGNED_INT, GL_FALSE, vertexStride, (void *)kCRTVertexOffsetOfTimestamp);
glVertexAttribPointer((GLuint)_openGL_state->lateralAttribute, 1, GL_UNSIGNED_BYTE, GL_FALSE, vertexStride, (void *)kCRTVertexOffsetOfLateral);
const GLsizei vertexStride = kCRTOutputVertexSize;
glVertexAttribPointer((GLuint)_openGL_state->positionAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)kCRTOutputVertexOffsetOfPosition);
glVertexAttribPointer((GLuint)_openGL_state->textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)kCRTOutputVertexOffsetOfTexCoord);
glVertexAttribPointer((GLuint)_openGL_state->timestampAttribute, 4, GL_UNSIGNED_INT, GL_FALSE, vertexStride, (void *)kCRTOutputVertexOffsetOfTimestamp);
glVertexAttribPointer((GLuint)_openGL_state->lateralAttribute, 1, GL_UNSIGNED_BYTE, GL_FALSE, vertexStride, (void *)kCRTOutputVertexOffsetOfLateral);
}
void CRT::set_output_device(OutputDevice output_device)
#pragma mark - Configuration
void CRT::set_output_device(CRT::OutputDevice output_device)
{
_output_device = output_device;
if (_output_device != output_device)
{
_output_device = output_device;
for(int builder = 0; builder < kCRTNumberOfFields; builder++)
{
_run_builders[builder]->reset();
}
_composite_src_runs->reset();
_composite_src_output_y = 0;
}
}

View File

@ -9,19 +9,33 @@
#ifndef CRTOpenGL_h
#define CRTOpenGL_h
const size_t kCRTVertexOffsetOfPosition = 0;
const size_t kCRTVertexOffsetOfTexCoord = 4;
const size_t kCRTVertexOffsetOfTimestamp = 8;
const size_t kCRTVertexOffsetOfLateral = 12;
// 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 kCRTOutputVertexOffsetOfPosition = 0;
const size_t kCRTOutputVertexOffsetOfTexCoord = 4;
const size_t kCRTOutputVertexOffsetOfTimestamp = 8;
const size_t kCRTOutputVertexOffsetOfLateral = 12;
const size_t kCRTSizeOfVertex = 16;
const size_t kCRTOutputVertexSize = 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 kCRTInputVertexOffsetOfInputPosition = 0;
const size_t kCRTInputVertexOffsetOfOutputPosition = 4;
const size_t kCRTInputVertexSize = 8;
// These constants hold the size of the rolling buffer to which the CPU writes
const int CRTInputBufferBuilderWidth = 2048;
const int CRTInputBufferBuilderHeight = 1024;
// This is the size of the intermediate buffers used during composite to RGB conversion
const int CRTIntermediateBufferWidth = 2048;
const int CRTIntermediateBufferHeight = 2048;
const int kCRTNumberOfFrames = 3;
// Runs are divided discretely by vertical syncs in order to put a usable bounds on the uniform used to track
// run age; that therefore creates a discrete number of fields that are stored. This number should be the
// number of historic fields that are required fully to
const int kCRTNumberOfFields = 3;
#endif /* CRTOpenGL_h */