1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-06 05:54:28 +00:00

Started trying to nudge towards the multistage approach to video decoding.

This commit is contained in:
Thomas Harte 2016-02-12 22:31:05 -05:00
parent 7bc5a43c36
commit fd2d5c78f8
2 changed files with 63 additions and 56 deletions

View File

@ -52,11 +52,12 @@ typedef struct {
uint8_t *vertices; uint8_t *vertices;
} CRTFrame; } CRTFrame;
// TODO: these should be private to whomever builds the shaders // The height of the intermediate buffers.
static const int kCRTFrameIntermediateBufferHeight = 2048;
static const size_t kCRTVertexOffsetOfPosition = 0; static const size_t kCRTVertexOffsetOfPosition = 0;
static const size_t kCRTVertexOffsetOfTexCoord = 4; static const size_t kCRTVertexOffsetOfTexCoord = 4;
static const size_t kCRTVertexOffsetOfLateral = 8; static const size_t kCRTVertexOffsetOfLateral = 8;
static const size_t kCRTVertexOffsetOfPhase = 9;
static const int kCRTSizeOfVertex = 10; static const int kCRTSizeOfVertex = 10;

View File

@ -1,4 +1,3 @@
// CRTOpenGL.cpp // CRTOpenGL.cpp
// Clock Signal // Clock Signal
// //
@ -16,7 +15,7 @@
using namespace Outputs; using namespace Outputs;
struct CRT::OpenGLState { struct CRT::OpenGLState {
OpenGL::Shader *shaderProgram; std::unique_ptr<OpenGL::Shader> shaderProgram;
GLuint arrayBuffer, vertexArray; GLuint arrayBuffer, vertexArray;
GLint positionAttribute; GLint positionAttribute;
@ -29,17 +28,13 @@ struct CRT::OpenGLState {
GLuint textureName, shadowMaskTextureName; GLuint textureName, shadowMaskTextureName;
GLuint defaultFramebuffer;
CRTSize textureSize; CRTSize textureSize;
OpenGL::TextureTarget *compositeTexture; std::unique_ptr<OpenGL::TextureTarget> compositeTexture; // receives raw composite levels
OpenGL::TextureTarget *colourTexture; std::unique_ptr<OpenGL::TextureTarget> filteredYTexture; // receives filtered Y in the R channel plus unfiltered I/U and Q/V in G and B
OpenGL::TextureTarget *filteredTexture; std::unique_ptr<OpenGL::TextureTarget> filteredTexture; // receives filtered YIQ or YUV
OpenGLState() : shaderProgram(nullptr) {}
~OpenGLState()
{
delete shaderProgram;
}
}; };
static GLenum formatForDepth(unsigned int depth) static GLenum formatForDepth(unsigned int depth)
@ -63,17 +58,42 @@ void CRT::construct_openGL()
void CRT::destruct_openGL() void CRT::destruct_openGL()
{ {
delete (OpenGLState *)_openGL_state; delete _openGL_state;
_openGL_state = nullptr;
if(_composite_shader) free(_composite_shader); if(_composite_shader) free(_composite_shader);
if(_rgb_shader) free(_rgb_shader); if(_rgb_shader) free(_rgb_shader);
} }
void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty) void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty)
{ {
_current_frame_mutex->lock(); // establish essentials
if(!_openGL_state)
{
_openGL_state = new OpenGLState;
GLint defaultFramebuffer; glGenTextures(1, &_openGL_state->textureName);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFramebuffer); glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenVertexArrays(1, &_openGL_state->vertexArray);
glBindVertexArray(_openGL_state->vertexArray);
glGenBuffers(1, &_openGL_state->arrayBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->arrayBuffer);
prepare_shader();
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&_openGL_state->defaultFramebuffer);
_openGL_state->compositeTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(2048, kCRTFrameIntermediateBufferHeight));
_openGL_state->filteredYTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(2048, kCRTFrameIntermediateBufferHeight));
_openGL_state->filteredTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(2048, kCRTFrameIntermediateBufferHeight));
}
// lock down any further work on the current frame
_current_frame_mutex->lock();
if(!_current_frame && !only_if_dirty) if(!_current_frame && !only_if_dirty)
{ {
@ -82,52 +102,37 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
if(_current_frame && (_current_frame != _last_drawn_frame || !only_if_dirty)) if(_current_frame && (_current_frame != _last_drawn_frame || !only_if_dirty))
{ {
glClear(GL_COLOR_BUFFER_BIT); // update uniforms
if(!_openGL_state)
{
_openGL_state = new OpenGLState;
glGenTextures(1, &_openGL_state->textureName);
glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenVertexArrays(1, &_openGL_state->vertexArray);
glBindVertexArray(_openGL_state->vertexArray);
glGenBuffers(1, &_openGL_state->arrayBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _openGL_state->arrayBuffer);
prepare_shader();
}
push_size_uniforms(output_width, output_height); push_size_uniforms(output_width, output_height);
if(_last_drawn_frame != nullptr)
{
glUniform1f(_openGL_state->alphaUniform, 0.4f);
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_last_drawn_frame->number_of_vertices);
}
glUniform1f(_openGL_state->alphaUniform, 1.0f); glUniform1f(_openGL_state->alphaUniform, 1.0f);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(_current_frame->number_of_vertices * _current_frame->size_per_vertex), _current_frame->vertices, GL_DYNAMIC_DRAW); // submit new frame data if required
if (_current_frame != _last_drawn_frame)
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); glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(_current_frame->number_of_vertices * _current_frame->size_per_vertex), _current_frame->vertices, GL_DYNAMIC_DRAW);
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) glBindTexture(GL_TEXTURE_2D, _openGL_state->textureName);
glUniform2f(_openGL_state->textureSizeUniform, _current_frame->size.width, _current_frame->size.height); 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);
} }
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
_openGL_state->compositeTexture->bind_framebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, _openGL_state->defaultFramebuffer);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_current_frame->number_of_vertices); glDrawArrays(GL_TRIANGLES, 0, (GLsizei)_current_frame->number_of_vertices);
_last_drawn_frame = _current_frame; _last_drawn_frame = _current_frame;
} }
@ -136,6 +141,7 @@ void CRT::draw_frame(unsigned int output_width, unsigned int output_height, bool
void CRT::set_openGL_context_will_change(bool should_delete_resources) void CRT::set_openGL_context_will_change(bool should_delete_resources)
{ {
_openGL_state = nullptr;
} }
void CRT::push_size_uniforms(unsigned int output_width, unsigned int output_height) void CRT::push_size_uniforms(unsigned int output_width, unsigned int output_height)
@ -290,7 +296,7 @@ void CRT::prepare_shader()
char *vertex_shader = get_vertex_shader(); char *vertex_shader = get_vertex_shader();
char *fragment_shader = get_fragment_shader(); char *fragment_shader = get_fragment_shader();
_openGL_state->shaderProgram = new OpenGL::Shader(vertex_shader, fragment_shader); _openGL_state->shaderProgram = std::unique_ptr<OpenGL::Shader>(new OpenGL::Shader(vertex_shader, fragment_shader));
_openGL_state->shaderProgram->bind(); _openGL_state->shaderProgram->bind();
_openGL_state->positionAttribute = _openGL_state->shaderProgram->get_attrib_location("position"); _openGL_state->positionAttribute = _openGL_state->shaderProgram->get_attrib_location("position");