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.
|
/// @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:
|
||||||
|
@ -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() {
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user