diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index 93c8d4d59..5a26574e3 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -73,44 +73,6 @@ struct ActivityObserver: public Activity::Observer { __unsafe_unretained CSMachine *machine; }; -//class ScanTarget: public Outputs::Display::ScanTarget { -// public: -// void set_modals(Modals m) { -// modals_ = m; -// } -// -// Scan *get_scan() { -// scans_.emplace_back(); -// return &scans_.back(); -// } -// -// uint8_t *allocate_write_area(size_t required_length, size_t required_alignment) { -// write_area_.resize(required_length); -// return write_area_.data(); -// } -// -// void submit(bool only_if_no_allocation_failures) { -// for(const auto &scan: scans_) { -// printf("%0.2f %0.2f [%0.2f] -> %0.2f %0.2f [%0.2f] => %0.2f\n", -// float(scan.end_points[0].x) / float(modals_.output_scale.x), -// float(scan.end_points[0].y) / float(modals_.output_scale.y), -// float(scan.end_points[0].composite_angle) / 64.0f, -// float(scan.end_points[1].x) / float(modals_.output_scale.x), -// float(scan.end_points[1].y) / float(modals_.output_scale.y), -// float(scan.end_points[1].composite_angle) / 64.0f, -// (float(scan.end_points[1].composite_angle - scan.end_points[0].composite_angle) / 64.0f) / (float(scan.end_points[1].x - scan.end_points[0].x) / float(modals_.output_scale.x)) -// ); -// } -// -// scans_.clear(); -// } -// -// private: -// std::vector scans_; -// std::vector write_area_; -// Modals modals_; -//}; - @implementation CSMachine { SpeakerDelegate _speakerDelegate; ActivityObserver _activityObserver; @@ -124,7 +86,7 @@ struct ActivityObserver: public Activity::Observer { std::bitset<65536> _depressedKeys; NSMutableArray *_leds; - Outputs::Display::OpenGL::ScanTarget _scanTarget; + std::unique_ptr _scanTarget; } - (instancetype)initWithAnalyser:(CSStaticAnalyser *)result { @@ -273,7 +235,8 @@ struct ActivityObserver: public Activity::Observer { } - (void)setupOutputWithAspectRatio:(float)aspectRatio { - _machine->crt_machine()->setup_output(&_scanTarget); + _scanTarget.reset(new Outputs::Display::OpenGL::ScanTarget); + _machine->crt_machine()->setup_output(_scanTarget.get()); // Since OS X v10.6, Macs have had a gamma of 2.2. // _machine->crt_machine()->get_crt()->set_output_gamma(2.2f); @@ -281,6 +244,7 @@ struct ActivityObserver: public Activity::Observer { } - (void)drawViewForPixelSize:(CGSize)pixelSize onlyIfDirty:(BOOL)onlyIfDirty { + _scanTarget->draw(); // _machine->crt_machine()->get_crt()->draw_frame((unsigned int)pixelSize.width, (unsigned int)pixelSize.height, onlyIfDirty ? true : false); } diff --git a/Outputs/OpenGL/ScanTarget.cpp b/Outputs/OpenGL/ScanTarget.cpp index f3727d26f..9bb8487d5 100644 --- a/Outputs/OpenGL/ScanTarget.cpp +++ b/Outputs/OpenGL/ScanTarget.cpp @@ -7,6 +7,7 @@ // #include "ScanTarget.hpp" +#include "Primitives/Rectangle.hpp" using namespace Outputs::Display::OpenGL; @@ -17,6 +18,19 @@ const int WriteAreaHeight = 2048; } +ScanTarget::ScanTarget() { + // Allocate space for the spans. + glGenBuffers(1, &scan_buffer_name_); + glBindBuffer(GL_ARRAY_BUFFER, scan_buffer_name_); + const auto buffer_size = scan_buffer_.size() * sizeof(Scan); + glBufferData(GL_ARRAY_BUFFER, GLsizeiptr(buffer_size), NULL, GL_STREAM_DRAW); +} + +ScanTarget::~ScanTarget() { + // Release span space. + glDeleteBuffers(1, &scan_buffer_name_); +} + void ScanTarget::set_modals(Modals modals) { // TODO: consider resizing the write_area_texture_, and setting // write_area_texture_line_length_ appropriately. @@ -89,5 +103,25 @@ void ScanTarget::reduce_previous_allocation_to(size_t actual_length) { } void ScanTarget::submit() { - // TODO. + if(allocation_has_failed_) { + // Reset all pointers to where they were. + scan_buffer_pointers_.write_pointer = scan_buffer_pointers_.submit_pointer; + } else { + // Advance submit pointer. + scan_buffer_pointers_.submit_pointer = scan_buffer_pointers_.write_pointer; + } + + allocation_has_failed_ = false; +} + +void ScanTarget::draw() { + // Submit spans. + if(scan_buffer_pointers_.submit_pointer != scan_buffer_pointers_.read_pointer) { + // TODO: submit all scans from scan_buffer_pointers_.read_pointer to scan_buffer_pointers_.submit_pointer. + scan_buffer_pointers_.read_pointer = scan_buffer_pointers_.submit_pointer; + } + + glClear(GL_COLOR_BUFFER_BIT); + ::OpenGL::Rectangle rect(-0.8f, -0.8f, 1.6f, 1.6f); + rect.draw(1, 1, 0); } diff --git a/Outputs/OpenGL/ScanTarget.hpp b/Outputs/OpenGL/ScanTarget.hpp index d2fa2eff6..6011c6397 100644 --- a/Outputs/OpenGL/ScanTarget.hpp +++ b/Outputs/OpenGL/ScanTarget.hpp @@ -10,6 +10,7 @@ #define ScanTarget_hpp #include "../ScanTarget.hpp" +#include "OpenGL.hpp" #include #include @@ -22,6 +23,11 @@ namespace OpenGL { class ScanTarget: public Outputs::Display::ScanTarget { public: + ScanTarget(); + ~ScanTarget(); + void draw(); + + // Outputs::Display::ScanTarget overrides. void set_modals(Modals) override; Scan *get_scan() override; uint8_t *allocate_write_area(size_t required_length, size_t required_alignment) override; @@ -39,10 +45,10 @@ class ScanTarget: public Outputs::Display::ScanTarget { }; template struct PointerSet { - /// A pointer to the final thing currently cleared for submission. - T submit_pointer; /// A pointer to the next thing that should be provided to the caller for data. T write_pointer; + /// A pointer to the final thing currently cleared for submission. + T submit_pointer; /// A pointer to the first thing not yet submitted for display. std::atomic read_pointer; }; @@ -50,6 +56,7 @@ class ScanTarget: public Outputs::Display::ScanTarget { // Maintains a buffer of the most recent 3072 scans. std::array scan_buffer_; PointerSet scan_buffer_pointers_; + GLuint scan_buffer_name_ = 0; // Uses a texture to vend write areas. std::vector write_area_texture_;