// Extends the definition of a Scan to include two extra fields,
// completing this scan's source data and destination locations.
structScan{
Outputs::Display::ScanTarget::Scanscan;
/// Stores the y coordinate for this scan's data within the write area texture.
/// Use this plus the scan's endpoints' data_offsets to locate this data in 2d.
uint16_tdata_y;
/// Stores the y coordinate assigned to this scan within the intermediate buffers.
/// Use this plus this scan's endpoints' x locations to determine where to composite
/// this data for intermediate processing.
uint16_tline;
};
/// Defines the boundaries of a complete line of video — a 2d start and end location,
/// composite phase and amplitude (if relevant), the source line in the intermediate buffer
/// plus the start and end offsets of the area that is visible from the intermediate buffer.
structLine{
structEndPoint{
uint16_tx,y;
uint16_tcycles_since_end_of_horizontal_retrace;
int16_tcomposite_angle;
}end_points[2];
uint16_tline;
uint8_tcomposite_amplitude;
};
/// Provides additional metadata about lines; this is separate because it's unlikely to be of
/// interest to the GPU, unlike the fields in Line.
structLineMetadata{
/// @c true if this line was the first drawn after vertical sync; @c false otherwise.
boolis_first_in_frame;
/// @c true if this line is the first in the frame and if every single piece of output
/// from the previous frame was recorded; @c false otherwise. Data can be dropped
/// from a frame if performance problems mean that the emulated machine is running
/// more quickly than complete frames can be generated.
boolprevious_frame_was_complete;
};
// TODO: put this behind accessors.
std::atomic_flagis_updating_;
// These are safe to read if you have is_updating_.
Modalsmodals_;
boolmodals_are_dirty_=false;
/// Maintains a buffer of the most recent scans.
// TODO: have the owner supply a buffer and its size.
// That'll allow owners to place this in shared video memory if possible.
std::array<Scan,16384>scan_buffer_;
structPointerSet{
// This constructor is here to appease GCC's interpretation of
// an ambiguity in the C++ standard; cf. https://stackoverflow.com/questions/17430377
PointerSet()noexcept{}
// Squeezing this struct into 64 bits makes the std::atomics more likely
// to be lock free; they are under LLVM x86-64.
intwrite_area=1;// By convention this points to the vended area. Which is preceded by a guard pixel. So a sensible default construction is write_area = 1.
uint16_tscan_buffer=0;
uint16_tline=0;
};
/// A pointer to the final thing currently cleared for submission.
std::atomic<PointerSet>submit_pointers_;
/// A pointer to the first thing not yet submitted for display.