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:
parent
cddd72876f
commit
c7ab3d4075
@ -94,6 +94,7 @@ enum class InputDataType {
|
||||
};
|
||||
|
||||
/// @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) {
|
||||
switch(data_type) {
|
||||
case InputDataType::Luminance1:
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
void BufferingScanTarget::end_data(size_t actual_length) {
|
||||
template <typename DataUnit> void BufferingScanTarget::end_data(size_t actual_length) {
|
||||
// Acquire the producer lock.
|
||||
std::lock_guard lock_guard(producer_mutex_);
|
||||
|
||||
// Do nothing if no data write is actually ongoing.
|
||||
if(allocation_has_failed_ || !data_is_allocated_) return;
|
||||
|
||||
// Bookend the start of the new data, to safeguard for precision errors in sampling.
|
||||
memcpy(
|
||||
&write_area_[size_t(write_pointers_.write_area - 1) * data_type_size_],
|
||||
&write_area_[size_t(write_pointers_.write_area) * data_type_size_],
|
||||
data_type_size_);
|
||||
// Bookend the start and end of the new data, to safeguard for precision errors in sampling.
|
||||
DataUnit *const sized_write_area = &reinterpret_cast<DataUnit *>(write_area_)[write_pointers_.write_area];
|
||||
sized_write_area[-1] = sized_write_area[0];
|
||||
sized_write_area[actual_length] = sized_write_area[actual_length - 1];
|
||||
|
||||
// Advance to the end of the current run.
|
||||
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
|
||||
// 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.
|
||||
@ -120,6 +113,16 @@ void BufferingScanTarget::end_data(size_t actual_length) {
|
||||
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.
|
||||
|
||||
Outputs::Display::ScanTarget::Scan *BufferingScanTarget::begin_scan() {
|
||||
|
@ -255,6 +255,11 @@ class BufferingScanTarget: public Outputs::Display::ScanTarget {
|
||||
Modals modals_;
|
||||
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
|
||||
// Debug features; these amount to API validation.
|
||||
bool scan_is_ongoing_ = false;
|
||||
|
Loading…
Reference in New Issue
Block a user