mirror of
https://github.com/TomHarte/CLK.git
synced 2024-08-21 04:29:34 +00:00
Ever more baby steps back towards composite decoding.
This commit is contained in:
parent
95efeb1d56
commit
70b6d51451
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user