1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-02 02:49:28 +00:00

Moves ownership of the scan and line buffers out of the BufferingScanTarget.

This commit is contained in:
Thomas Harte 2020-07-26 22:46:03 -04:00
parent bc6426313e
commit 77c5b86acc
4 changed files with 51 additions and 22 deletions

View File

@ -79,6 +79,9 @@ ScanTarget::ScanTarget(GLuint target_framebuffer, float output_gamma) :
unprocessed_line_texture_(LineBufferWidth, LineBufferHeight, UnprocessedLineBufferTextureUnit, GL_NEAREST, false), unprocessed_line_texture_(LineBufferWidth, LineBufferHeight, UnprocessedLineBufferTextureUnit, GL_NEAREST, false),
full_display_rectangle_(-1.0f, -1.0f, 2.0f, 2.0f) { full_display_rectangle_(-1.0f, -1.0f, 2.0f, 2.0f) {
set_scan_buffer(scan_buffer_.data(), scan_buffer_.size());
set_line_buffer(line_buffer_.data(), line_metadata_buffer_.data(), line_buffer_.size());
// Allocate space for the scans and lines. // Allocate space for the scans and lines.
allocate_buffer(scan_buffer_, scan_buffer_name_, scan_vertex_array_); allocate_buffer(scan_buffer_, scan_buffer_name_, scan_vertex_array_);
allocate_buffer(line_buffer_, line_buffer_name_, line_vertex_array_); allocate_buffer(line_buffer_, line_buffer_name_, line_vertex_array_);
@ -253,7 +256,7 @@ void ScanTarget::update(int, int output_height) {
1 + area.end.write_area_y - area.start.write_area_y, 1 + area.end.write_area_y - area.start.write_area_y,
formatForDepth(write_area_data_size()), formatForDepth(write_area_data_size()),
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
&write_area_texture_[size_t(TextureAddress(0, area.start.write_area_y)) * write_area_data_size()]); &write_area_texture_[size_t(area.start.write_area_y * WriteAreaWidth) * write_area_data_size()]);
} else { } else {
// The circular buffer wrapped around; submit the data from the read pointer to the end of // 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. // the buffer and from the start of the buffer to the submit pointer.
@ -264,7 +267,7 @@ void ScanTarget::update(int, int output_height) {
WriteAreaHeight - area.start.write_area_y, WriteAreaHeight - area.start.write_area_y,
formatForDepth(write_area_data_size()), formatForDepth(write_area_data_size()),
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
&write_area_texture_[size_t(TextureAddress(0, area.start.write_area_y)) * write_area_data_size()]); &write_area_texture_[size_t(area.start.write_area_y * WriteAreaWidth) * write_area_data_size()]);
test_gl(glTexSubImage2D, test_gl(glTexSubImage2D,
GL_TEXTURE_2D, 0, GL_TEXTURE_2D, 0,
0, 0, 0, 0,

View File

@ -51,6 +51,9 @@ class ScanTarget: public Outputs::Display::BufferingScanTarget {
void update(int output_width, int output_height); void update(int output_width, int output_height);
private: private:
static constexpr int LineBufferWidth = 2048;
static constexpr int LineBufferHeight = 2048;
#ifndef NDEBUG #ifndef NDEBUG
struct OpenGLVersionDumper { struct OpenGLVersionDumper {
OpenGLVersionDumper() { OpenGLVersionDumper() {
@ -146,8 +149,11 @@ class ScanTarget: public Outputs::Display::BufferingScanTarget {
*/ */
bool is_soft_display_type(); bool is_soft_display_type();
// Storage for the write area. // Storage for the various buffers.
std::vector<uint8_t> write_area_texture_; std::vector<uint8_t> write_area_texture_;
std::array<Scan, 16384> scan_buffer_;
std::array<Line, LineBufferHeight> line_buffer_;
std::array<LineMetadata, LineBufferHeight> line_metadata_buffer_;
}; };
} }

View File

@ -14,6 +14,7 @@
#define TextureAddressGetY(v) uint16_t((v) >> 11) #define TextureAddressGetY(v) uint16_t((v) >> 11)
#define TextureAddressGetX(v) uint16_t((v) & 0x7ff) #define TextureAddressGetX(v) uint16_t((v) & 0x7ff)
#define TextureSub(a, b) (((a) - (b)) & 0x3fffff) #define TextureSub(a, b) (((a) - (b)) & 0x3fffff)
#define TextureAddress(x, y) (((y) << 11) | (x))
using namespace Outputs::Display; using namespace Outputs::Display;
@ -162,7 +163,7 @@ void BufferingScanTarget::announce(Event event, bool is_visible, const Outputs::
} }
// Attempt to allocate a new line; note allocation failure if necessary. // Attempt to allocate a new line; note allocation failure if necessary.
const auto next_line = uint16_t((write_pointers_.line + 1) % LineBufferHeight); const auto next_line = uint16_t((write_pointers_.line + 1) % line_buffer_size_);
if(next_line == read_pointers.line) { if(next_line == read_pointers.line) {
allocation_has_failed_ = true; allocation_has_failed_ = true;
active_line_ = nullptr; active_line_ = nullptr;
@ -229,7 +230,7 @@ Outputs::Display::ScanTarget::Scan *BufferingScanTarget::begin_scan() {
const auto read_pointers = read_pointers_.load(); const auto read_pointers = read_pointers_.load();
// Advance the pointer. // Advance the pointer.
const auto next_write_pointer = decltype(write_pointers_.scan_buffer)((write_pointers_.scan_buffer + 1) % scan_buffer_.size()); const auto next_write_pointer = decltype(write_pointers_.scan_buffer)((write_pointers_.scan_buffer + 1) % scan_buffer_size_);
// Check whether that's too many. // Check whether that's too many.
if(next_write_pointer == read_pointers.scan_buffer) { if(next_write_pointer == read_pointers.scan_buffer) {
@ -298,3 +299,14 @@ void BufferingScanTarget::perform(const std::function<void(void)> &function) {
function(); function();
is_updating_.clear(std::memory_order_release); is_updating_.clear(std::memory_order_release);
} }
void BufferingScanTarget::set_scan_buffer(Scan *buffer, size_t size) {
scan_buffer_ = buffer;
scan_buffer_size_ = size;
}
void BufferingScanTarget::set_line_buffer(Line *line_buffer, LineMetadata *metadata_buffer, size_t size) {
line_buffer_ = line_buffer;
line_metadata_buffer_ = metadata_buffer;
line_buffer_size_ = size;
}

View File

@ -18,8 +18,6 @@
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#define TextureAddress(x, y) (((y) << 11) | (x))
namespace Outputs { namespace Outputs {
namespace Display { namespace Display {
@ -45,9 +43,6 @@ class BufferingScanTarget: public Outputs::Display::ScanTarget {
static constexpr int WriteAreaWidth = 2048; static constexpr int WriteAreaWidth = 2048;
static constexpr int WriteAreaHeight = 2048; static constexpr int WriteAreaHeight = 2048;
static constexpr int LineBufferWidth = 2048;
static constexpr int LineBufferHeight = 2048;
BufferingScanTarget(); BufferingScanTarget();
// This is included because it's assumed that scan targets will want to expose one. // This is included because it's assumed that scan targets will want to expose one.
@ -93,22 +88,23 @@ class BufferingScanTarget: public Outputs::Display::ScanTarget {
bool previous_frame_was_complete; bool previous_frame_was_complete;
}; };
/// Sets the area of memory to use as a scan buffer.
void set_scan_buffer(Scan *buffer, size_t size);
/// Sets the area of memory to use as line and line metadata buffers.
void set_line_buffer(Line *line_buffer, LineMetadata *metadata_buffer, size_t size);
// These are safe to read only within a `perform` block. // These are safe to read only within a `perform` block.
// TODO: can I do better than that? // TODO: can I do better than that?
Modals modals_; Modals modals_;
bool modals_are_dirty_ = false; bool modals_are_dirty_ = false;
/// Maintains a buffer of the most recent scans. /// Sets a new base address for the texture.
// TODO: have the owner supply buffers and sizes. /// When called this will flush all existing data and load up the
// That'll allow owners to place this in shared video memory if possible. /// new data size.
std::array<Scan, 16384> scan_buffer_;
std::array<Line, LineBufferHeight> line_buffer_;
std::array<LineMetadata, LineBufferHeight> line_metadata_buffer_;
// Used by subclasses to set a new base address for the texture.
// When called this will flush all existing data and load up the
// new data size.
void set_write_area(uint8_t *base); void set_write_area(uint8_t *base);
/// @returns The number of bytes per input sample, as per the latest modals.
size_t write_area_data_size() const; size_t write_area_data_size() const;
/// Defines a segment of data now ready for output, consisting of start and endpoints for: /// Defines a segment of data now ready for output, consisting of start and endpoints for:
@ -130,9 +126,12 @@ class BufferingScanTarget: public Outputs::Display::ScanTarget {
Endpoint start, end; Endpoint start, end;
}; };
void perform(const std::function<void(const OutputArea &)> &); /// Performs @c action ensuring that no other @c perform actions, or any
void perform(const std::function<void(void)> &); /// change to modals, occurs simultaneously.
void perform(const std::function<void(void)> &action);
/// Acts as per void(void) @c perform but also dequeues all latest available video output.
void perform(const std::function<void(const OutputArea &)> &);
private: private:
// ScanTarget overrides. // ScanTarget overrides.
@ -205,6 +204,15 @@ class BufferingScanTarget: public Outputs::Display::ScanTarget {
/// A pointer to the next thing that should be provided to the caller for data. /// A pointer to the next thing that should be provided to the caller for data.
PointerSet write_pointers_; PointerSet write_pointers_;
// The owner-supplied scan buffer and size.
Scan *scan_buffer_ = nullptr;
size_t scan_buffer_size_ = 0;
// The owner-supplied line buffer and size.
Line *line_buffer_ = nullptr;
LineMetadata *line_metadata_buffer_ = nullptr;
size_t line_buffer_size_ = 0;
}; };