1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-25 03:32:01 +00:00

Tidied up a little, mostly bumping things out of just-in-time creation that I can just do well in advance.

This commit is contained in:
Thomas Harte 2016-04-12 22:31:13 -04:00
parent 069ec2e889
commit fe8b0ebc7e
2 changed files with 100 additions and 102 deletions

View File

@ -12,52 +12,6 @@
#include "CRTOpenGL.hpp" #include "CRTOpenGL.hpp"
#include "../../../SignalProcessing/FIRFilter.hpp" #include "../../../SignalProcessing/FIRFilter.hpp"
using namespace Outputs::CRT;
namespace {
static const GLenum first_supplied_buffer_texture_unit = 3;
}
OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) :
_run_write_pointer(0),
_output_mutex(new std::mutex),
_visible_area(Rect(0, 0, 1, 1)),
_composite_src_output_y(0),
_composite_shader(nullptr),
_rgb_shader(nullptr),
_output_buffer_data(nullptr),
_output_buffer_sync(nullptr),
_input_texture_data(nullptr)
{
_run_builders = new CRTRunBuilder *[NumberOfFields];
for(int builder = 0; builder < NumberOfFields; builder++)
{
_run_builders[builder] = new CRTRunBuilder();
}
// _composite_src_runs = std::unique_ptr<CRTRunBuilder>(new CRTRunBuilder(InputVertexSize));
_buffer_builder = std::unique_ptr<CRTInputBufferBuilder>(new CRTInputBufferBuilder(buffer_depth));
}
OpenGLOutputBuilder::~OpenGLOutputBuilder()
{
for(int builder = 0; builder < NumberOfFields; builder++)
{
delete _run_builders[builder];
}
delete[] _run_builders;
glUnmapBuffer(GL_ARRAY_BUFFER);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glDeleteTextures(1, &textureName);
glDeleteBuffers(1, &_input_texture_array);
glDeleteBuffers(1, &output_array_buffer);
glDeleteVertexArrays(1, &output_vertex_array);
free(_composite_shader);
free(_rgb_shader);
}
static const GLint internalFormatForDepth(size_t depth) static const GLint internalFormatForDepth(size_t depth)
{ {
switch(depth) switch(depth)
@ -82,46 +36,62 @@ static const GLenum formatForDepth(size_t depth)
} }
} }
void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty)
using namespace Outputs::CRT;
namespace {
static const GLenum first_supplied_buffer_texture_unit = 3;
}
OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) :
_run_write_pointer(0),
_output_mutex(new std::mutex),
_visible_area(Rect(0, 0, 1, 1)),
_composite_src_output_y(0),
_composite_shader(nullptr),
_rgb_shader(nullptr),
_output_buffer_data(nullptr),
_output_buffer_sync(nullptr),
_input_texture_data(nullptr),
_output_buffer_data_pointer(0)
{ {
// establish essentials _run_builders = new CRTRunBuilder *[NumberOfFields];
if(!composite_input_shader_program && !rgb_shader_program) for(int builder = 0; builder < NumberOfFields; builder++)
{ {
// generate and bind texture for input data _run_builders[builder] = new CRTRunBuilder();
glGenTextures(1, &textureName); }
glActiveTexture(GL_TEXTURE0 + first_supplied_buffer_texture_unit); _buffer_builder = std::unique_ptr<CRTInputBufferBuilder>(new CRTInputBufferBuilder(buffer_depth));
glBindTexture(GL_TEXTURE_2D, 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);
glGenBuffers(1, &_input_texture_array); // create the surce texture
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _input_texture_array); glGenTextures(1, &textureName);
_input_texture_array_size = (GLsizeiptr)(InputBufferBuilderWidth * InputBufferBuilderHeight * _buffer_builder->bytes_per_pixel); glActiveTexture(GL_TEXTURE0 + first_supplied_buffer_texture_unit);
glBufferData(GL_PIXEL_UNPACK_BUFFER, _input_texture_array_size, NULL, GL_STREAM_DRAW); glBindTexture(GL_TEXTURE_2D, 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);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormatForDepth(_buffer_builder->bytes_per_pixel), InputBufferBuilderWidth, InputBufferBuilderHeight, 0, formatForDepth(_buffer_builder->bytes_per_pixel), GL_UNSIGNED_BYTE, nullptr);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormatForDepth(_buffer_builder->bytes_per_pixel), InputBufferBuilderWidth, InputBufferBuilderHeight, 0, formatForDepth(_buffer_builder->bytes_per_pixel), GL_UNSIGNED_BYTE, nullptr); // create a pixel unpack buffer
glGenBuffers(1, &_input_texture_array);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _input_texture_array);
_input_texture_array_size = (GLsizeiptr)(InputBufferBuilderWidth * InputBufferBuilderHeight * _buffer_builder->bytes_per_pixel);
glBufferData(GL_PIXEL_UNPACK_BUFFER, _input_texture_array_size, NULL, GL_STREAM_DRAW);
prepare_composite_input_shader(); // map the buffer for clients
prepare_rgb_output_shader(); _input_texture_data = (uint8_t *)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, _input_texture_array_size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
glGenVertexArrays(1, &output_vertex_array); // create the output vertex array
glGenBuffers(1, &output_array_buffer); glGenVertexArrays(1, &output_vertex_array);
output_vertices_per_slice = 0; glBindVertexArray(output_vertex_array);
glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); // create a buffer for output vertex attributes
glGenBuffers(1, &output_array_buffer);
glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer);
glBufferData(GL_ARRAY_BUFFER, OutputVertexBufferDataSize, NULL, GL_STREAM_DRAW);
glBufferData(GL_ARRAY_BUFFER, OutputVertexBufferDataSize, NULL, GL_STREAM_DRAW); // map that buffer too, for any CRT activity that may occur before the first draw
_output_buffer_data_pointer = 0; _output_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, OutputVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
glBindVertexArray(output_vertex_array);
prepare_output_vertex_array();
// This should return either an actual framebuffer number, if this is a target with a framebuffer intended for output,
// or 0 if no framebuffer is bound, in which case 0 is also what we want to supply to bind the implied framebuffer. So
// it works either way.
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&defaultFramebuffer);
// Create intermediate textures and bind to slots 0, 1 and 2 // Create intermediate textures and bind to slots 0, 1 and 2
// glActiveTexture(GL_TEXTURE0); // glActiveTexture(GL_TEXTURE0);
@ -130,6 +100,40 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
// filteredYTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(IntermediateBufferWidth, IntermediateBufferHeight)); // filteredYTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(IntermediateBufferWidth, IntermediateBufferHeight));
// glActiveTexture(GL_TEXTURE2); // glActiveTexture(GL_TEXTURE2);
// filteredTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(IntermediateBufferWidth, IntermediateBufferHeight)); // filteredTexture = std::unique_ptr<OpenGL::TextureTarget>(new OpenGL::TextureTarget(IntermediateBufferWidth, IntermediateBufferHeight));
}
OpenGLOutputBuilder::~OpenGLOutputBuilder()
{
for(int builder = 0; builder < NumberOfFields; builder++)
{
delete _run_builders[builder];
}
delete[] _run_builders;
glUnmapBuffer(GL_ARRAY_BUFFER);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glDeleteTextures(1, &textureName);
glDeleteBuffers(1, &_input_texture_array);
glDeleteBuffers(1, &output_array_buffer);
glDeleteVertexArrays(1, &output_vertex_array);
free(_composite_shader);
free(_rgb_shader);
}
void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty)
{
// establish essentials
if(!composite_input_shader_program && !rgb_shader_program)
{
prepare_composite_input_shader();
prepare_rgb_output_shader();
prepare_output_vertex_array();
// This should return either an actual framebuffer number, if this is a target with a framebuffer intended for output,
// or 0 if no framebuffer is bound, in which case 0 is also what we want to supply to bind the implied framebuffer. So
// it works either way.
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&defaultFramebuffer);
} }
// lock down any further work on the current frame // lock down any further work on the current frame
@ -145,29 +149,25 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
// upload more source pixel data if any; we'll always resubmit the last line submitted last // 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 // time as it may have had extra data appended to it
// for(unsigned int buffer = 0; buffer < _buffer_builder->number_of_buffers; buffer++) if(_buffer_builder->_next_write_y_position < _buffer_builder->last_uploaded_line)
// { {
// glActiveTexture(GL_TEXTURE0 + first_supplied_buffer_texture_unit + buffer); glTexSubImage2D( GL_TEXTURE_2D, 0,
if(_buffer_builder->_next_write_y_position < _buffer_builder->last_uploaded_line) 0, (GLint)_buffer_builder->last_uploaded_line,
{ InputBufferBuilderWidth, (GLint)(InputBufferBuilderHeight - _buffer_builder->last_uploaded_line),
glTexSubImage2D( GL_TEXTURE_2D, 0, formatForDepth(_buffer_builder->bytes_per_pixel), GL_UNSIGNED_BYTE,
0, (GLint)_buffer_builder->last_uploaded_line, (void *)(_buffer_builder->last_uploaded_line * InputBufferBuilderWidth * _buffer_builder->bytes_per_pixel));
InputBufferBuilderWidth, (GLint)(InputBufferBuilderHeight - _buffer_builder->last_uploaded_line), _buffer_builder->last_uploaded_line = 0;
formatForDepth(_buffer_builder->bytes_per_pixel), GL_UNSIGNED_BYTE, }
(void *)(_buffer_builder->last_uploaded_line * InputBufferBuilderWidth * _buffer_builder->bytes_per_pixel));
_buffer_builder->last_uploaded_line = 0;
}
if(_buffer_builder->_next_write_y_position > _buffer_builder->last_uploaded_line) if(_buffer_builder->_next_write_y_position > _buffer_builder->last_uploaded_line)
{ {
glTexSubImage2D( GL_TEXTURE_2D, 0, glTexSubImage2D( GL_TEXTURE_2D, 0,
0, (GLint)_buffer_builder->last_uploaded_line, 0, (GLint)_buffer_builder->last_uploaded_line,
InputBufferBuilderWidth, (GLint)(1 + _buffer_builder->_next_write_y_position - _buffer_builder->last_uploaded_line), InputBufferBuilderWidth, (GLint)(1 + _buffer_builder->_next_write_y_position - _buffer_builder->last_uploaded_line),
formatForDepth(_buffer_builder->bytes_per_pixel), GL_UNSIGNED_BYTE, formatForDepth(_buffer_builder->bytes_per_pixel), GL_UNSIGNED_BYTE,
(void *)(_buffer_builder->last_uploaded_line * InputBufferBuilderWidth * _buffer_builder->bytes_per_pixel)); (void *)(_buffer_builder->last_uploaded_line * InputBufferBuilderWidth * _buffer_builder->bytes_per_pixel));
_buffer_builder->last_uploaded_line = _buffer_builder->_next_write_y_position; _buffer_builder->last_uploaded_line = _buffer_builder->_next_write_y_position;
} }
// }
// check for anything to decode from composite // check for anything to decode from composite
// if(_composite_src_runs->number_of_vertices) // if(_composite_src_runs->number_of_vertices)
@ -230,7 +230,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
} }
// drawing commands having been issued, reclaim the array buffer pointer // drawing commands having been issued, reclaim the array buffer pointer
// _buffer_builder->move_to_new_line();
_output_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, OutputVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); _output_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, OutputVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
_input_texture_data = (uint8_t *)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, _input_texture_array_size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); _input_texture_data = (uint8_t *)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, _input_texture_array_size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
_output_mutex->unlock(); _output_mutex->unlock();

View File

@ -75,7 +75,6 @@ class OpenGLOutputBuilder {
std::unique_ptr<OpenGL::Shader> composite_input_shader_program, composite_output_shader_program; std::unique_ptr<OpenGL::Shader> composite_input_shader_program, composite_output_shader_program;
GLuint output_array_buffer, output_vertex_array; GLuint output_array_buffer, output_vertex_array;
size_t output_vertices_per_slice;
GLint windowSizeUniform, timestampBaseUniform; GLint windowSizeUniform, timestampBaseUniform;
GLint boundsOriginUniform, boundsSizeUniform; GLint boundsOriginUniform, boundsSizeUniform;