From 0af1d668a6269a64fc93683b0312d3140b1123dc Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 12 Nov 2018 18:47:55 -0500 Subject: [PATCH] Takes a first step towards generality, and thereby starts submitting lines. --- Outputs/OpenGL/ScanTarget.cpp | 85 ++++++++++++++++++++--------------- Outputs/OpenGL/ScanTarget.hpp | 10 +++-- 2 files changed, 56 insertions(+), 39 deletions(-) diff --git a/Outputs/OpenGL/ScanTarget.cpp b/Outputs/OpenGL/ScanTarget.cpp index b9e7d323f..88a907098 100644 --- a/Outputs/OpenGL/ScanTarget.cpp +++ b/Outputs/OpenGL/ScanTarget.cpp @@ -66,14 +66,19 @@ const GLenum formatForDepth(std::size_t depth) { } +template void ScanTarget::allocate_buffer(const T &array, GLuint &buffer_name) { + const auto buffer_size = array.size() * sizeof(array[0]); + glGenBuffers(1, &buffer_name); + glBindBuffer(GL_ARRAY_BUFFER, buffer_name); + glBufferData(GL_ARRAY_BUFFER, GLsizeiptr(buffer_size), NULL, GL_STREAM_DRAW); +} + ScanTarget::ScanTarget() : unprocessed_line_texture_(LineBufferWidth, LineBufferHeight, UnprocessedLineBufferTextureUnit, GL_LINEAR) { - // Allocate space for the scans. - const auto buffer_size = scan_buffer_.size() * sizeof(Scan); - glGenBuffers(1, &scan_buffer_name_); - glBindBuffer(GL_ARRAY_BUFFER, scan_buffer_name_); - glBufferData(GL_ARRAY_BUFFER, GLsizeiptr(buffer_size), NULL, GL_STREAM_DRAW); + // Allocate space for the scans and lines. + allocate_buffer(scan_buffer_, scan_buffer_name_); + allocate_buffer(line_buffer_, line_buffer_name_); // TODO: if this is OpenGL 4.4 or newer, use glBufferStorage rather than glBufferData // and specify GL_MAP_PERSISTENT_BIT. Then map the buffer now, and let the client @@ -243,6 +248,42 @@ void ScanTarget::announce(Event event, uint16_t x, uint16_t y) { } } +template void ScanTarget::submit_buffer(const T &array, GLuint target, uint16_t submit_pointer, uint16_t read_pointer) { + if(submit_pointer != read_pointer) { + // Bind the buffer and map it into CPU space. + glBindBuffer(GL_ARRAY_BUFFER, target); + const auto buffer_size = array.size() * sizeof(array[0]); + uint8_t *destination = static_cast( + glMapBufferRange(GL_ARRAY_BUFFER, 0, GLsizeiptr(buffer_size), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT) + ); + assert(destination); + + if(submit_pointer > read_pointer) { + // Submit the direct region from the submit pointer to the read pointer. + const size_t offset = read_pointer * sizeof(array[0]); + const size_t length = (submit_pointer - read_pointer) * sizeof(array[0]); + memcpy(&destination[offset], &array[read_pointer], length); + + glFlushMappedBufferRange(GL_ARRAY_BUFFER, GLintptr(offset), GLsizeiptr(length)); + } else { + // The circular buffer wrapped around; submit the data from the read pointer to the end of + // the buffer and from the start of the buffer to the submit pointer. + const size_t offset = read_pointer * sizeof(array[0]); + const size_t end_length = (array.size() - read_pointer) * sizeof(array[0]); + const size_t start_length = submit_pointer * sizeof(array[0]); + + memcpy(&destination[offset], &array[read_pointer], end_length); + memcpy(&destination[0], &array[0], start_length); + + glFlushMappedBufferRange(GL_ARRAY_BUFFER, GLintptr(offset), GLsizeiptr(end_length)); + glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, GLsizeiptr(start_length)); + } + + // Unmap the buffer. + glUnmapBuffer(GL_ARRAY_BUFFER); + } +} + void ScanTarget::draw() { glClear(GL_COLOR_BUFFER_BIT); @@ -250,37 +291,9 @@ void ScanTarget::draw() { const auto submit_pointers = submit_pointers_.load(); const auto read_pointers = read_pointers_.load(); - // Submit scans. - if(submit_pointers.scan_buffer != read_pointers.scan_buffer) { - const auto buffer_size = scan_buffer_.size() * sizeof(Scan); - uint8_t *destination = static_cast( - glMapBufferRange(GL_ARRAY_BUFFER, 0, GLsizeiptr(buffer_size), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT) - ); - assert(destination); - - if(submit_pointers.scan_buffer > read_pointers.scan_buffer) { - // Submit the direct region from the submit pointer to the read pointer. - const size_t offset = read_pointers.scan_buffer * sizeof(Scan); - const size_t length = (submit_pointers.scan_buffer - read_pointers.scan_buffer) * sizeof(Scan); - memcpy(&destination[offset], &scan_buffer_[read_pointers.scan_buffer], length); - - glFlushMappedBufferRange(GL_ARRAY_BUFFER, GLintptr(offset), GLsizeiptr(length)); - } else { - // The circular buffer wrapped around; submit the data from the read pointer to the end of - // the buffer and from the start of the buffer to the submit pointer. - const size_t offset = read_pointers.scan_buffer * sizeof(Scan); - const size_t end_length = (scan_buffer_.size() - read_pointers.scan_buffer) * sizeof(Scan); - const size_t start_length = submit_pointers.scan_buffer * sizeof(Scan); - - memcpy(&destination[offset], &scan_buffer_[read_pointers.scan_buffer], end_length); - memcpy(&destination[0], &scan_buffer_[0], start_length); - - glFlushMappedBufferRange(GL_ARRAY_BUFFER, GLintptr(offset), GLsizeiptr(end_length)); - glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, GLsizeiptr(start_length)); - } - - glUnmapBuffer(GL_ARRAY_BUFFER); - } + // Submit scans and lines. + submit_buffer(scan_buffer_, scan_buffer_name_, submit_pointers.scan_buffer, read_pointers.scan_buffer); + submit_buffer(line_buffer_, line_buffer_name_, submit_pointers.line, read_pointers.line); // Submit texture. if(submit_pointers.write_area != read_pointers.write_area) { diff --git a/Outputs/OpenGL/ScanTarget.hpp b/Outputs/OpenGL/ScanTarget.hpp index 897f129b0..8e108b25d 100644 --- a/Outputs/OpenGL/ScanTarget.hpp +++ b/Outputs/OpenGL/ScanTarget.hpp @@ -70,8 +70,6 @@ class ScanTarget: public Outputs::Display::ScanTarget { // Maintains a buffer of the most recent 3072 scans. std::array scan_buffer_; - GLuint scan_buffer_name_ = 0; - GLuint scan_vertex_array_ = 0; // Maintains a list of composite scan buffer coordinates. struct Line { @@ -82,9 +80,15 @@ class ScanTarget: public Outputs::Display::ScanTarget { }; std::array line_buffer_; TextureTarget unprocessed_line_texture_; - GLuint line_vertex_array_ = 0; Line *active_line_ = nullptr; + // OpenGL storage handles for buffer data. + GLuint scan_buffer_name_ = 0, scan_vertex_array_ = 0; + GLuint line_buffer_name_ = 0, line_vertex_array_ = 0; + + template void allocate_buffer(const T &array, GLuint &buffer_name); + template void submit_buffer(const T &array, GLuint target, uint16_t submit_pointer, uint16_t read_pointer); + // Uses a texture to vend write areas. std::vector write_area_texture_; size_t data_type_size_ = 0;