From cb3c837e308f3bd4f425f80b83d0abd91a97eb39 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 3 Dec 2016 18:19:12 -0500 Subject: [PATCH] Simplified interface by baking in last-minute-only updates. --- Outputs/CRT/CRT.cpp | 18 ++++++++-------- Outputs/CRT/Internals/ArrayBuilder.cpp | 29 +++++++++----------------- Outputs/CRT/Internals/ArrayBuilder.hpp | 15 +++---------- 3 files changed, 22 insertions(+), 40 deletions(-) diff --git a/Outputs/CRT/CRT.cpp b/Outputs/CRT/CRT.cpp index 3f68cddfe..e4791c740 100644 --- a/Outputs/CRT/CRT.cpp +++ b/Outputs/CRT/CRT.cpp @@ -140,7 +140,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi source_input_position_y() = tex_y; source_output_position_x1() = (uint16_t)horizontal_flywheel_->get_current_output_position(); // Don't write output_y now, write it later; we won't necessarily know what it is outside of the locked region -// source_output_position_y() = openGL_output_builder_->get_composite_output_y(); source_phase() = colour_burst_phase_; source_amplitude() = colour_burst_amplitude_; source_phase_time() = (uint8_t)colour_burst_time_; // assumption: burst was within the first 1/16 of the line @@ -193,13 +192,7 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi openGL_output_builder_.lock_output(); // Get and write all those previously unwritten output ys - uint16_t output_y = openGL_output_builder_.get_composite_output_y(); - size_t size; - uint8_t *buffered_lines = openGL_output_builder_.array_builder.get_unflushed_input(size); - for(size_t position = 0; position < size; position += SourceVertexSize) - { - (*(uint16_t *)&buffered_lines[position + SourceVertexOffsetOfOutputStart + 2]) = output_y; - } + const uint16_t output_y = openGL_output_builder_.get_composite_output_y(); // Construct the output run uint8_t *next_run = openGL_output_builder_.array_builder.get_output_storage(OutputVertexSize); @@ -210,7 +203,14 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi output_tex_y() = output_y; output_x2() = (uint16_t)horizontal_flywheel_->get_current_output_position(); } - openGL_output_builder_.array_builder.flush(); + openGL_output_builder_.array_builder.flush( + [output_y] (uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t output_size) + { + for(size_t position = 0; position < input_size; position += SourceVertexSize) + { + (*(uint16_t *)&input_buffer[position + SourceVertexOffsetOfOutputStart + 2]) = output_y; + } + }); openGL_output_builder_.unlock_output(); } diff --git a/Outputs/CRT/Internals/ArrayBuilder.cpp b/Outputs/CRT/Internals/ArrayBuilder.cpp index c934b3a5e..53a97e1b1 100644 --- a/Outputs/CRT/Internals/ArrayBuilder.cpp +++ b/Outputs/CRT/Internals/ArrayBuilder.cpp @@ -23,9 +23,8 @@ ArrayBuilder::ArrayBuilder(size_t input_size, size_t output_size, std::function< bool ArrayBuilder::is_full() { bool was_full; - buffer_mutex_.lock(); + std::lock_guard guard(buffer_mutex_); was_full = is_full_; - buffer_mutex_.unlock(); return was_full; } @@ -34,30 +33,24 @@ uint8_t *ArrayBuilder::get_input_storage(size_t size) return get_storage(size, input_); } -uint8_t *ArrayBuilder::get_unflushed_input(size_t &size) -{ - return input_.get_unflushed(size); -} - uint8_t *ArrayBuilder::get_output_storage(size_t size) { return get_storage(size, output_); } -uint8_t *ArrayBuilder::get_unflushed_output(size_t &size) +void ArrayBuilder::flush(const std::function &function) { - return output_.get_unflushed(size); -} - -void ArrayBuilder::flush() -{ - buffer_mutex_.lock(); + std::lock_guard guard(buffer_mutex_); if(!is_full_) { + size_t input_size, output_size; + uint8_t *input = input_.get_unflushed(input_size); + uint8_t *output = output_.get_unflushed(output_size); + function(input, input_size, output, output_size); + input_.flush(); output_.flush(); } - buffer_mutex_.unlock(); } void ArrayBuilder::bind_input() @@ -74,7 +67,7 @@ ArrayBuilder::Submission ArrayBuilder::submit() { ArrayBuilder::Submission submission; - buffer_mutex_.lock(); + std::lock_guard guard(buffer_mutex_); submission.input_size = input_.submit(true); submission.output_size = output_.submit(false); if(is_full_) @@ -83,7 +76,6 @@ ArrayBuilder::Submission ArrayBuilder::submit() input_.reset(); output_.reset(); } - buffer_mutex_.unlock(); return submission; } @@ -110,10 +102,9 @@ ArrayBuilder::Buffer::~Buffer() uint8_t *ArrayBuilder::get_storage(size_t size, Buffer &buffer) { - buffer_mutex_.lock(); + std::lock_guard guard(buffer_mutex_); uint8_t *pointer = buffer.get_storage(size); if(!pointer) is_full_ = true; - buffer_mutex_.unlock(); return pointer; } diff --git a/Outputs/CRT/Internals/ArrayBuilder.hpp b/Outputs/CRT/Internals/ArrayBuilder.hpp index ed72b98af..0be0644c6 100644 --- a/Outputs/CRT/Internals/ArrayBuilder.hpp +++ b/Outputs/CRT/Internals/ArrayBuilder.hpp @@ -41,26 +41,17 @@ class ArrayBuilder { /// @returns a pointer to the allocated area if allocation was possible; @c nullptr otherwise. uint8_t *get_input_storage(size_t size); - /// Gets the size of and a pointer to all data so far added to the input set but not yet flushed. - /// @returns a pointer from which it is safe to access @c size elements, which contains all regions returned via - /// @c get_input_storage in FIFO order. - uint8_t *get_unflushed_input(size_t &size); - /// Attempts to add @c size bytes to the output set. /// @returns a pointer to the allocated area if allocation was possible; @c nullptr otherwise. uint8_t *get_output_storage(size_t size); - /// Gets the size of and a pointer to all data so far added to the output set but not yet flushed. - /// @returns a pointer from which it is safe to access @c size elements, which contains all regions returned via - /// @c get_input_storage in FIFO order. - uint8_t *get_unflushed_output(size_t &size); - /// @returns @c true if either of the input or output storage areas is currently exhausted; @c false otherwise. bool is_full(); /// If neither input nor output was exhausted since the last flush, atomically commits both input and output - /// up to the currently allocated size for use upon the next @c submit. Otherwise acts as a no-op. - void flush(); + /// up to the currently allocated size for use upon the next @c submit, giving the supplied function a + /// chance to perform last-minute processing. Otherwise acts as a no-op. + void flush(const std::function &); /// Binds the input array to GL_ARRAY_BUFFER. void bind_input();