1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Reduces cost of bookending video data.

This commit is contained in:
Thomas Harte 2020-11-18 17:32:11 -05:00
parent cddd72876f
commit c7ab3d4075
3 changed files with 21 additions and 12 deletions

View File

@ -94,6 +94,7 @@ enum class InputDataType {
}; };
/// @returns the number of bytes per sample for data of type @c data_type. /// @returns the number of bytes per sample for data of type @c data_type.
/// Guaranteed to be 1, 2 or 4 for valid data types.
constexpr inline size_t size_for_data_type(InputDataType data_type) { constexpr inline size_t size_for_data_type(InputDataType data_type) {
switch(data_type) { switch(data_type) {
case InputDataType::Luminance1: case InputDataType::Luminance1:

View File

@ -89,28 +89,21 @@ uint8_t *BufferingScanTarget::begin_data(size_t required_length, size_t required
// write_pointers_.write_area points to the first pixel the client is expected to draw to. // write_pointers_.write_area points to the first pixel the client is expected to draw to.
} }
void BufferingScanTarget::end_data(size_t actual_length) { template <typename DataUnit> void BufferingScanTarget::end_data(size_t actual_length) {
// Acquire the producer lock. // Acquire the producer lock.
std::lock_guard lock_guard(producer_mutex_); std::lock_guard lock_guard(producer_mutex_);
// Do nothing if no data write is actually ongoing. // Do nothing if no data write is actually ongoing.
if(allocation_has_failed_ || !data_is_allocated_) return; if(allocation_has_failed_ || !data_is_allocated_) return;
// Bookend the start of the new data, to safeguard for precision errors in sampling. // Bookend the start and end of the new data, to safeguard for precision errors in sampling.
memcpy( DataUnit *const sized_write_area = &reinterpret_cast<DataUnit *>(write_area_)[write_pointers_.write_area];
&write_area_[size_t(write_pointers_.write_area - 1) * data_type_size_], sized_write_area[-1] = sized_write_area[0];
&write_area_[size_t(write_pointers_.write_area) * data_type_size_], sized_write_area[actual_length] = sized_write_area[actual_length - 1];
data_type_size_);
// Advance to the end of the current run. // Advance to the end of the current run.
write_pointers_.write_area += actual_length + 1; write_pointers_.write_area += actual_length + 1;
// Also bookend the end.
memcpy(
&write_area_[size_t(write_pointers_.write_area - 1) * data_type_size_],
&write_area_[size_t(write_pointers_.write_area - 2) * data_type_size_],
data_type_size_);
// The write area was allocated in the knowledge that there's sufficient // The write area was allocated in the knowledge that there's sufficient
// distance left on the current line, but there's a risk of exactly filling // distance left on the current line, but there's a risk of exactly filling
// the final line, in which case this should wrap back to 0. // the final line, in which case this should wrap back to 0.
@ -120,6 +113,16 @@ void BufferingScanTarget::end_data(size_t actual_length) {
data_is_allocated_ = false; data_is_allocated_ = false;
} }
void BufferingScanTarget::end_data(size_t actual_length) {
// Just dispatch appropriately.
switch(data_type_size_) {
default: break;
case 1: end_data<uint8_t>(actual_length); break;
case 2: end_data<uint16_t>(actual_length); break;
case 4: end_data<uint32_t>(actual_length); break;
}
}
// MARK: - Producer; scans. // MARK: - Producer; scans.
Outputs::Display::ScanTarget::Scan *BufferingScanTarget::begin_scan() { Outputs::Display::ScanTarget::Scan *BufferingScanTarget::begin_scan() {

View File

@ -255,6 +255,11 @@ class BufferingScanTarget: public Outputs::Display::ScanTarget {
Modals modals_; Modals modals_;
bool modals_are_dirty_ = false; bool modals_are_dirty_ = false;
// Provides a per-data size implementation of end_data; a previous
// implementation used blind memcpy and that turned into something
// of a profiling hot spot.
template <typename DataUnit> void end_data(size_t actual_length);
#ifndef NDEBUG #ifndef NDEBUG
// Debug features; these amount to API validation. // Debug features; these amount to API validation.
bool scan_is_ongoing_ = false; bool scan_is_ongoing_ = false;