mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-24 12:30:17 +00:00
Screen output is back, no matter how inefficiently.
This commit is contained in:
parent
d0b2d840da
commit
697e50c0cc
@ -79,7 +79,8 @@ void CRT::set_new_display_type(unsigned int cycles_per_line, DisplayType display
|
|||||||
|
|
||||||
void CRT::allocate_buffers(unsigned int number, va_list sizes)
|
void CRT::allocate_buffers(unsigned int number, va_list sizes)
|
||||||
{
|
{
|
||||||
for(int builder = 0; builder < sizeof(_run_builders) / sizeof(*_run_builders); builder++)
|
_run_builders = new CRTRunBuilder *[kCRTNumberOfFrames];
|
||||||
|
for(int builder = 0; builder < kCRTNumberOfFrames; builder++)
|
||||||
{
|
{
|
||||||
_run_builders[builder] = new CRTRunBuilder();
|
_run_builders[builder] = new CRTRunBuilder();
|
||||||
}
|
}
|
||||||
@ -104,10 +105,11 @@ CRT::CRT() :
|
|||||||
|
|
||||||
CRT::~CRT()
|
CRT::~CRT()
|
||||||
{
|
{
|
||||||
for(int builder = 0; builder < sizeof(_run_builders) / sizeof(*_run_builders); builder++)
|
for(int builder = 0; builder < kCRTNumberOfFrames; builder++)
|
||||||
{
|
{
|
||||||
delete _run_builders[builder];
|
delete _run_builders[builder];
|
||||||
}
|
}
|
||||||
|
delete[] _run_builders;
|
||||||
destruct_openGL();
|
destruct_openGL();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +173,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
#define tex_x(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTexCoord + 0])
|
#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 tex_y(v) (*(uint16_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTexCoord + 2])
|
||||||
#define lateral(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfLateral]
|
#define lateral(v) next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfLateral]
|
||||||
|
#define timestamp(v) (*(uint32_t *)&next_run[kCRTSizeOfVertex*v + kCRTVertexOffsetOfTimestamp])
|
||||||
|
|
||||||
#define InternalToUInt16(v) ((v) + 32768) >> 16
|
#define InternalToUInt16(v) ((v) + 32768) >> 16
|
||||||
#define CounterToInternal(c) (unsigned int)(((uint64_t)c->get_current_output_position() * kCRTFixedPointRange) / c->get_scan_period())
|
#define CounterToInternal(c) (unsigned int)(((uint64_t)c->get_current_output_position() * kCRTFixedPointRange) / c->get_scan_period())
|
||||||
@ -186,6 +189,8 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
position_x(1) = InternalToUInt16(kCRTFixedPointOffset + x_position - _beamWidth[lengthMask].x);
|
position_x(1) = InternalToUInt16(kCRTFixedPointOffset + x_position - _beamWidth[lengthMask].x);
|
||||||
position_y(1) = InternalToUInt16(kCRTFixedPointOffset + y_position - _beamWidth[lengthMask].y);
|
position_y(1) = InternalToUInt16(kCRTFixedPointOffset + y_position - _beamWidth[lengthMask].y);
|
||||||
|
|
||||||
|
timestamp(0) = timestamp(1) = timestamp(4) = _run_builders[_run_write_pointer]->duration;
|
||||||
|
|
||||||
tex_x(0) = tex_x(1) = tex_x(4) = tex_x;
|
tex_x(0) = tex_x(1) = tex_x(4) = tex_x;
|
||||||
|
|
||||||
// these things are constants across the line so just throw them out now
|
// these things are constants across the line so just throw them out now
|
||||||
@ -197,6 +202,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
// decrement the number of cycles left to run for and increment the
|
// decrement the number of cycles left to run for and increment the
|
||||||
// horizontal counter appropriately
|
// horizontal counter appropriately
|
||||||
number_of_cycles -= next_run_length;
|
number_of_cycles -= next_run_length;
|
||||||
|
_run_builders[_run_write_pointer]->duration += next_run_length;
|
||||||
|
|
||||||
// either charge or deplete the vertical retrace capacitor (making sure it stops at 0)
|
// either charge or deplete the vertical retrace capacitor (making sure it stops at 0)
|
||||||
if (vsync_charging && !_vertical_flywheel->is_in_retrace())
|
if (vsync_charging && !_vertical_flywheel->is_in_retrace())
|
||||||
@ -219,6 +225,8 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
|
|||||||
position_x(5) = InternalToUInt16(kCRTFixedPointOffset + x_position + _beamWidth[lengthMask].x);
|
position_x(5) = InternalToUInt16(kCRTFixedPointOffset + x_position + _beamWidth[lengthMask].x);
|
||||||
position_y(5) = InternalToUInt16(kCRTFixedPointOffset + y_position + _beamWidth[lengthMask].y);
|
position_y(5) = InternalToUInt16(kCRTFixedPointOffset + y_position + _beamWidth[lengthMask].y);
|
||||||
|
|
||||||
|
timestamp(2) = timestamp(3) = timestamp(5) = _run_builders[_run_write_pointer]->duration;
|
||||||
|
|
||||||
// if this is a data run then advance the buffer pointer
|
// if this is a data run then advance the buffer pointer
|
||||||
if(type == Type::Data && source_divider) tex_x += next_run_length / (_time_multiplier * source_divider);
|
if(type == Type::Data && source_divider) tex_x += next_run_length / (_time_multiplier * source_divider);
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ class CRT {
|
|||||||
|
|
||||||
// Storage for the length of run data uploaded so far; reset to zero by reset but otherwise
|
// Storage for the length of run data uploaded so far; reset to zero by reset but otherwise
|
||||||
// entrusted to the CRT to update.
|
// entrusted to the CRT to update.
|
||||||
size_t uploaded_run_data;
|
size_t uploaded_vertices;
|
||||||
size_t number_of_vertices;
|
size_t number_of_vertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -326,9 +326,8 @@ class CRT {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// the run and input data buffers
|
// the run and input data buffers
|
||||||
static const int kCRTNumberOfFrames = 4;
|
|
||||||
std::unique_ptr<CRTInputBufferBuilder> _buffer_builder;
|
std::unique_ptr<CRTInputBufferBuilder> _buffer_builder;
|
||||||
CRTRunBuilder *_run_builders[kCRTNumberOfFrames];
|
CRTRunBuilder **_run_builders;
|
||||||
int _run_write_pointer;
|
int _run_write_pointer;
|
||||||
std::shared_ptr<std::mutex> _output_mutex;
|
std::shared_ptr<std::mutex> _output_mutex;
|
||||||
|
|
||||||
@ -346,6 +345,7 @@ class CRT {
|
|||||||
|
|
||||||
// Methods used by the OpenGL code
|
// Methods used by the OpenGL code
|
||||||
void prepare_shader();
|
void prepare_shader();
|
||||||
|
void prepare_vertex_array();
|
||||||
void push_size_uniforms(unsigned int output_width, unsigned int output_height);
|
void push_size_uniforms(unsigned int output_width, unsigned int output_height);
|
||||||
|
|
||||||
char *get_vertex_shader();
|
char *get_vertex_shader();
|
||||||
|
@ -82,6 +82,8 @@ uint8_t *CRT::CRTInputBufferBuilder::get_write_target_for_buffer(int buffer)
|
|||||||
void CRT::CRTRunBuilder::reset()
|
void CRT::CRTRunBuilder::reset()
|
||||||
{
|
{
|
||||||
number_of_vertices = 0;
|
number_of_vertices = 0;
|
||||||
|
uploaded_vertices = 0;
|
||||||
|
duration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *CRT::CRTRunBuilder::get_next_input_run()
|
uint8_t *CRT::CRTRunBuilder::get_next_input_run()
|
||||||
|
@ -17,15 +17,15 @@ using namespace Outputs;
|
|||||||
|
|
||||||
struct CRT::OpenGLState {
|
struct CRT::OpenGLState {
|
||||||
std::unique_ptr<OpenGL::Shader> shaderProgram;
|
std::unique_ptr<OpenGL::Shader> shaderProgram;
|
||||||
GLuint arrayBuffer, vertexArray;
|
GLuint arrayBuffers[kCRTNumberOfFrames], vertexArrays[kCRTNumberOfFrames];
|
||||||
|
|
||||||
GLint positionAttribute;
|
GLint positionAttribute;
|
||||||
GLint textureCoordinatesAttribute;
|
GLint textureCoordinatesAttribute;
|
||||||
GLint lateralAttribute;
|
GLint lateralAttribute;
|
||||||
|
GLint timestampAttribute;
|
||||||
|
|
||||||
GLint textureSizeUniform, windowSizeUniform;
|
GLint windowSizeUniform, timestampBaseUniform;
|
||||||
GLint boundsOriginUniform, boundsSizeUniform;
|
GLint boundsOriginUniform, boundsSizeUniform;
|
||||||
GLint alphaUniform;
|
|
||||||
|
|
||||||
GLuint textureName, shadowMaskTextureName;
|
GLuint textureName, shadowMaskTextureName;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ struct CRT::OpenGLState {
|
|||||||
std::unique_ptr<OpenGL::TextureTarget> filteredTexture; // receives filtered YIQ or YUV
|
std::unique_ptr<OpenGL::TextureTarget> filteredTexture; // receives filtered YIQ or YUV
|
||||||
};
|
};
|
||||||
|
|
||||||
static GLenum formatForDepth(unsigned int depth)
|
static GLenum formatForDepth(size_t depth)
|
||||||
{
|
{
|
||||||
switch(depth)
|
switch(depth)
|
||||||
{
|
{
|
||||||
@ -76,13 +76,21 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
glGenVertexArrays(1, &_openGL_state->vertexArray);
|
GLenum format = formatForDepth(_buffer_builder->buffers[0].bytes_per_pixel);
|
||||||
glBindVertexArray(_openGL_state->vertexArray);
|
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight, 0, format, GL_UNSIGNED_BYTE, _buffer_builder->buffers[0].data);
|
||||||
glGenBuffers(1, &_openGL_state->arrayBuffer);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->arrayBuffer);
|
glGenVertexArrays(kCRTNumberOfFrames, _openGL_state->vertexArrays);
|
||||||
|
glGenBuffers(kCRTNumberOfFrames, _openGL_state->arrayBuffers);
|
||||||
|
|
||||||
prepare_shader();
|
prepare_shader();
|
||||||
|
|
||||||
|
for(int c = 0; c < kCRTNumberOfFrames; c++)
|
||||||
|
{
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->arrayBuffers[c]);
|
||||||
|
glBindVertexArray(_openGL_state->vertexArrays[c]);
|
||||||
|
prepare_vertex_array();
|
||||||
|
}
|
||||||
|
|
||||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&_openGL_state->defaultFramebuffer);
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&_openGL_state->defaultFramebuffer);
|
||||||
|
|
||||||
// _openGL_state->compositeTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(2048, kCRTFrameIntermediateBufferHeight));
|
// _openGL_state->compositeTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(2048, kCRTFrameIntermediateBufferHeight));
|
||||||
@ -95,28 +103,56 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
|
|||||||
|
|
||||||
// update uniforms
|
// update uniforms
|
||||||
push_size_uniforms(output_width, output_height);
|
push_size_uniforms(output_width, output_height);
|
||||||
glUniform1f(_openGL_state->alphaUniform, 1.0f);
|
|
||||||
|
|
||||||
// submit latest frame data if required
|
// clear the buffer
|
||||||
/* glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(current_frame->number_of_vertices * current_frame->size_per_vertex), current_frame->vertices, GL_DYNAMIC_DRAW);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName);
|
|
||||||
if(_openGL_state->textureSize.width != _current_frame->size.width || _openGL_state->textureSize.height != _current_frame->size.height)
|
|
||||||
{
|
|
||||||
GLenum format = formatForDepth(_current_frame->buffers[0].depth);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, _current_frame->size.width, _current_frame->size.height, 0, format, GL_UNSIGNED_BYTE, _current_frame->buffers[0].data);
|
|
||||||
_openGL_state->textureSize = _current_frame->size;
|
|
||||||
|
|
||||||
if(_openGL_state->textureSizeUniform >= 0)
|
|
||||||
glUniform2f(_openGL_state->textureSizeUniform, _current_frame->size.width, _current_frame->size.height);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _current_frame->size.width, _current_frame->dirty_size.height, formatForDepth(_current_frame->buffers[0].depth), GL_UNSIGNED_BYTE, _current_frame->buffers[0].data);
|
|
||||||
|
|
||||||
// draw
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, _openGL_state->defaultFramebuffer);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_current_frame->number_of_vertices);*/
|
|
||||||
|
// upload more source pixel data if any; we'll always resubmit the last line submitted last
|
||||||
|
// time as it may have had extra data appended to it
|
||||||
|
GLenum format = formatForDepth(_buffer_builder->buffers[0].bytes_per_pixel);
|
||||||
|
// if(_buffer_builder->_next_write_y_position > _buffer_builder->last_uploaded_line)
|
||||||
|
// {
|
||||||
|
// glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (GLint)_buffer_builder->last_uploaded_line, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight, format, GL_UNSIGNED_BYTE, &_buffer_builder->buffers[0].data[_buffer_builder->last_uploaded_line * CRTInputBufferBuilderWidth * _buffer_builder->buffers[0].bytes_per_pixel]);
|
||||||
|
// _buffer_builder->last_uploaded_line = _buffer_builder->_next_write_y_position;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight, 0, format, GL_UNSIGNED_BYTE, _buffer_builder->buffers[0].data);
|
||||||
|
_buffer_builder->last_uploaded_line = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// draw all sitting frames
|
||||||
|
int run = _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++)
|
||||||
|
{
|
||||||
|
// update the total age at the start of this set of runs
|
||||||
|
total_age += _run_builders[run]->duration;
|
||||||
|
|
||||||
|
if(_run_builders[run]->number_of_vertices > 0)
|
||||||
|
{
|
||||||
|
glUniform1f(_openGL_state->timestampBaseUniform, (GLfloat)total_age);
|
||||||
|
|
||||||
|
// bind the vertex array
|
||||||
|
glBindVertexArray(_openGL_state->vertexArrays[run]);
|
||||||
|
|
||||||
|
// bind this frame's array buffer
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->arrayBuffers[run]);
|
||||||
|
if(_run_builders[run]->uploaded_vertices != _run_builders[run]->number_of_vertices)
|
||||||
|
{
|
||||||
|
// buffersubdata can only replace existing data, not grow the pool, so we'll just have to take this hit
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(_run_builders[run]->number_of_vertices * kCRTSizeOfVertex), &_run_builders[run]->_input_runs[0], GL_DYNAMIC_DRAW);
|
||||||
|
_run_builders[run]->uploaded_vertices = _run_builders[run]->number_of_vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw this frame
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_run_builders[run]->number_of_vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance back in time
|
||||||
|
run = (run - 1 + kCRTNumberOfFrames) % kCRTNumberOfFrames;
|
||||||
|
}
|
||||||
|
|
||||||
_output_mutex->unlock();
|
_output_mutex->unlock();
|
||||||
}
|
}
|
||||||
@ -183,14 +219,18 @@ char *CRT::get_vertex_shader()
|
|||||||
"in vec2 position;"
|
"in vec2 position;"
|
||||||
"in vec2 srcCoordinates;"
|
"in vec2 srcCoordinates;"
|
||||||
"in float lateral;"
|
"in float lateral;"
|
||||||
|
"in float timestamp;"
|
||||||
|
|
||||||
"uniform vec2 boundsOrigin;"
|
"uniform vec2 boundsOrigin;"
|
||||||
"uniform vec2 boundsSize;"
|
"uniform vec2 boundsSize;"
|
||||||
|
|
||||||
"out float lateralVarying;"
|
"out float lateralVarying;"
|
||||||
"out vec2 shadowMaskCoordinates;"
|
"out vec2 shadowMaskCoordinates;"
|
||||||
|
"out float age;"
|
||||||
|
|
||||||
"uniform vec2 textureSize;"
|
"uniform vec2 textureSize;"
|
||||||
|
"uniform float timestampBase;"
|
||||||
|
"uniform float ticksPerFrame;"
|
||||||
|
|
||||||
"const float shadowMaskMultiple = 600;"
|
"const float shadowMaskMultiple = 600;"
|
||||||
|
|
||||||
@ -202,7 +242,8 @@ char *CRT::get_vertex_shader()
|
|||||||
|
|
||||||
"shadowMaskCoordinates = position * vec2(shadowMaskMultiple, shadowMaskMultiple * 0.85057471264368);"
|
"shadowMaskCoordinates = position * vec2(shadowMaskMultiple, shadowMaskMultiple * 0.85057471264368);"
|
||||||
|
|
||||||
"srcCoordinatesVarying = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);\n"
|
"srcCoordinatesVarying = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);"
|
||||||
|
"age = (timestampBase - timestamp) / ticksPerFrame;"
|
||||||
|
|
||||||
"vec2 mappedPosition = (position - boundsOrigin) / boundsSize;"
|
"vec2 mappedPosition = (position - boundsOrigin) / boundsSize;"
|
||||||
"gl_Position = vec4(mappedPosition.x * 2.0 - 1.0, 1.0 - mappedPosition.y * 2.0, 0.0, 1.0);"
|
"gl_Position = vec4(mappedPosition.x * 2.0 - 1.0, 1.0 - mappedPosition.y * 2.0, 0.0, 1.0);"
|
||||||
@ -247,20 +288,19 @@ char *CRT::get_fragment_shader()
|
|||||||
"#version 150\n"
|
"#version 150\n"
|
||||||
|
|
||||||
"in float lateralVarying;"
|
"in float lateralVarying;"
|
||||||
|
"in float age;"
|
||||||
"in vec2 shadowMaskCoordinates;"
|
"in vec2 shadowMaskCoordinates;"
|
||||||
"out vec4 fragColour;"
|
"out vec4 fragColour;"
|
||||||
|
|
||||||
"uniform sampler2D texID;"
|
"uniform sampler2D texID;"
|
||||||
"uniform sampler2D shadowMaskTexID;"
|
"uniform sampler2D shadowMaskTexID;"
|
||||||
"uniform float alpha;"
|
|
||||||
|
|
||||||
"in vec2 srcCoordinatesVarying;"
|
"in vec2 srcCoordinatesVarying;"
|
||||||
"in float phase;\n"
|
"\n%s\n"
|
||||||
"%s\n"
|
|
||||||
|
|
||||||
"void main(void)"
|
"void main(void)"
|
||||||
"{"
|
"{"
|
||||||
"fragColour = vec4(rgb_sample(srcCoordinatesVarying).rgb, alpha);"
|
"fragColour = vec4(rgb_sample(srcCoordinatesVarying).rgb, 1.3 - age);"
|
||||||
"}"
|
"}"
|
||||||
, _rgb_shader);
|
, _rgb_shader);
|
||||||
}
|
}
|
||||||
@ -284,26 +324,36 @@ void CRT::prepare_shader()
|
|||||||
_openGL_state->positionAttribute = _openGL_state->shaderProgram->get_attrib_location("position");
|
_openGL_state->positionAttribute = _openGL_state->shaderProgram->get_attrib_location("position");
|
||||||
_openGL_state->textureCoordinatesAttribute = _openGL_state->shaderProgram->get_attrib_location("srcCoordinates");
|
_openGL_state->textureCoordinatesAttribute = _openGL_state->shaderProgram->get_attrib_location("srcCoordinates");
|
||||||
_openGL_state->lateralAttribute = _openGL_state->shaderProgram->get_attrib_location("lateral");
|
_openGL_state->lateralAttribute = _openGL_state->shaderProgram->get_attrib_location("lateral");
|
||||||
_openGL_state->alphaUniform = _openGL_state->shaderProgram->get_uniform_location("alpha");
|
_openGL_state->timestampAttribute = _openGL_state->shaderProgram->get_attrib_location("timestamp");
|
||||||
_openGL_state->textureSizeUniform = _openGL_state->shaderProgram->get_uniform_location("textureSize");
|
|
||||||
_openGL_state->windowSizeUniform = _openGL_state->shaderProgram->get_uniform_location("windowSize");
|
_openGL_state->windowSizeUniform = _openGL_state->shaderProgram->get_uniform_location("windowSize");
|
||||||
_openGL_state->boundsSizeUniform = _openGL_state->shaderProgram->get_uniform_location("boundsSize");
|
_openGL_state->boundsSizeUniform = _openGL_state->shaderProgram->get_uniform_location("boundsSize");
|
||||||
_openGL_state->boundsOriginUniform = _openGL_state->shaderProgram->get_uniform_location("boundsOrigin");
|
_openGL_state->boundsOriginUniform = _openGL_state->shaderProgram->get_uniform_location("boundsOrigin");
|
||||||
|
_openGL_state->timestampBaseUniform = _openGL_state->shaderProgram->get_uniform_location("timestampBase");
|
||||||
|
|
||||||
GLint texIDUniform = _openGL_state->shaderProgram->get_uniform_location("texID");
|
GLint texIDUniform = _openGL_state->shaderProgram->get_uniform_location("texID");
|
||||||
GLint shadowMaskTexIDUniform = _openGL_state->shaderProgram->get_uniform_location("shadowMaskTexID");
|
GLint shadowMaskTexIDUniform = _openGL_state->shaderProgram->get_uniform_location("shadowMaskTexID");
|
||||||
|
GLint textureSizeUniform = _openGL_state->shaderProgram->get_uniform_location("textureSize");
|
||||||
|
GLint ticksPerFrameUniform = _openGL_state->shaderProgram->get_uniform_location("ticksPerFrame");
|
||||||
|
|
||||||
glUniform1i(texIDUniform, 0);
|
glUniform1i(texIDUniform, 0);
|
||||||
glUniform1i(shadowMaskTexIDUniform, 1);
|
glUniform1i(shadowMaskTexIDUniform, 1);
|
||||||
|
glUniform2f(textureSizeUniform, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight);
|
||||||
|
glUniform1f(ticksPerFrameUniform, (GLfloat)(_cycles_per_line * _height_of_display * _time_multiplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRT::prepare_vertex_array()
|
||||||
|
{
|
||||||
glEnableVertexAttribArray((GLuint)_openGL_state->positionAttribute);
|
glEnableVertexAttribArray((GLuint)_openGL_state->positionAttribute);
|
||||||
glEnableVertexAttribArray((GLuint)_openGL_state->textureCoordinatesAttribute);
|
glEnableVertexAttribArray((GLuint)_openGL_state->textureCoordinatesAttribute);
|
||||||
glEnableVertexAttribArray((GLuint)_openGL_state->lateralAttribute);
|
glEnableVertexAttribArray((GLuint)_openGL_state->lateralAttribute);
|
||||||
|
glEnableVertexAttribArray((GLuint)_openGL_state->timestampBaseUniform);
|
||||||
|
|
||||||
const GLsizei vertexStride = kCRTSizeOfVertex;
|
const GLsizei vertexStride = kCRTSizeOfVertex;
|
||||||
glVertexAttribPointer((GLuint)_openGL_state->positionAttribute, 2, GL_UNSIGNED_SHORT, GL_TRUE, vertexStride, (void *)kCRTVertexOffsetOfPosition);
|
glVertexAttribPointer((GLuint)_openGL_state->positionAttribute, 2, GL_UNSIGNED_SHORT, GL_TRUE, vertexStride, (void *)kCRTVertexOffsetOfPosition);
|
||||||
glVertexAttribPointer((GLuint)_openGL_state->textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)kCRTVertexOffsetOfTexCoord);
|
glVertexAttribPointer((GLuint)_openGL_state->textureCoordinatesAttribute, 2, GL_UNSIGNED_SHORT, GL_FALSE, vertexStride, (void *)kCRTVertexOffsetOfTexCoord);
|
||||||
glVertexAttribPointer((GLuint)_openGL_state->lateralAttribute, 1, GL_UNSIGNED_BYTE, GL_FALSE, vertexStride, (void *)kCRTVertexOffsetOfLateral);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRT::set_output_device(OutputDevice output_device)
|
void CRT::set_output_device(OutputDevice output_device)
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
#define CRTOpenGL_h
|
#define CRTOpenGL_h
|
||||||
|
|
||||||
const size_t kCRTVertexOffsetOfPosition = 0;
|
const size_t kCRTVertexOffsetOfPosition = 0;
|
||||||
const size_t kCRTVertexOffsetOfTexCoord = 2;
|
const size_t kCRTVertexOffsetOfTexCoord = 4;
|
||||||
const size_t kCRTVertexOffsetOfTimestamp = 4;
|
const size_t kCRTVertexOffsetOfTimestamp = 8;
|
||||||
const size_t kCRTVertexOffsetOfLateral = 8;
|
const size_t kCRTVertexOffsetOfLateral = 12;
|
||||||
|
|
||||||
const size_t kCRTSizeOfVertex = 10;
|
const size_t kCRTSizeOfVertex = 16;
|
||||||
|
|
||||||
const int CRTInputBufferBuilderWidth = 2048;
|
const int CRTInputBufferBuilderWidth = 2048;
|
||||||
const int CRTInputBufferBuilderHeight = 1024;
|
const int CRTInputBufferBuilderHeight = 1024;
|
||||||
@ -22,4 +22,6 @@ const int CRTInputBufferBuilderHeight = 1024;
|
|||||||
const int CRTIntermediateBufferWidth = 2048;
|
const int CRTIntermediateBufferWidth = 2048;
|
||||||
const int CRTIntermediateBufferHeight = 2048;
|
const int CRTIntermediateBufferHeight = 2048;
|
||||||
|
|
||||||
|
const int kCRTNumberOfFrames = 3;
|
||||||
|
|
||||||
#endif /* CRTOpenGL_h */
|
#endif /* CRTOpenGL_h */
|
||||||
|
Loading…
Reference in New Issue
Block a user