openMSX
FrameSource.hh
Go to the documentation of this file.
1#ifndef FRAMESOURCE_HH
2#define FRAMESOURCE_HH
3
4#include "aligned.hh"
5#include "narrow.hh"
6#include "xrange.hh"
7#include <algorithm>
8#include <array>
9#include <cassert>
10#include <concepts>
11#include <span>
12
13namespace openmsx {
14
15class PixelFormat;
16
20{
21public:
24 enum FieldType {
34 };
35
39 void init(FieldType fieldType_) { fieldType = fieldType_; }
40
43 [[nodiscard]] FieldType getField() const {
44 return fieldType;
45 }
46
49 [[nodiscard]] unsigned getHeight() const {
50 return height;
51 }
52
56 [[nodiscard]] virtual unsigned getLineWidth(unsigned line) const = 0;
57
64 [[nodiscard]] unsigned getWidth() const {
65 assert(height > 0);
66 unsigned result = getLineWidth(0);
67 for (auto line : xrange(1u, height)) {
68 assert(result == getLineWidth(line)); (void)line;
69 }
70 return result;
71 }
72
78 template<std::unsigned_integral Pixel>
79 [[nodiscard]] inline Pixel getLineColor(unsigned line) const {
80 ALIGNAS_SSE std::array<Pixel, 1280> buf; // large enough for widest line
81 unsigned width; // not used
82 return reinterpret_cast<const Pixel*>(
83 getLineInfo(line, width, buf.data(), 1280))[0];
84 }
85
95 template<std::unsigned_integral Pixel>
96 [[nodiscard]] inline std::span<const Pixel> getLine(int line, std::span<Pixel> buf) const
97 {
98 line = std::clamp(line, 0, narrow<int>(getHeight() - 1));
99 unsigned internalWidth;
100 auto* internalData = reinterpret_cast<const Pixel*>(
101 getLineInfo(line, internalWidth, buf.data(), narrow<unsigned>(buf.size())));
102 if (internalWidth == narrow<unsigned>(buf.size())) {
103 return std::span{internalData, buf.size()};
104 } else {
105 // slow path, non-inlined
106 // internalData might be equal to buf
107 scaleLine(std::span{internalData, internalWidth}, buf);
108 return buf;
109 }
110 }
111
125 [[nodiscard]] virtual const void* getLineInfo(
126 unsigned line, unsigned& lineWidth,
127 void* buf, unsigned bufWidth) const = 0;
128
134 template<std::unsigned_integral Pixel>
135 [[nodiscard]] std::span<const Pixel, 320> getLinePtr320_240(unsigned line, std::span<Pixel, 320> buf) const;
136
141 template<std::unsigned_integral Pixel>
142 [[nodiscard]] std::span<const Pixel, 640> getLinePtr640_480(unsigned line, std::span<Pixel, 640> buf) const;
143
148 template<std::unsigned_integral Pixel>
149 [[nodiscard]] std::span<const Pixel, 960> getLinePtr960_720(unsigned line, std::span<Pixel, 960> buf) const;
150
151 [[nodiscard]] const PixelFormat& getPixelFormat() const {
152 return pixelFormat;
153 }
154
155protected:
156 explicit FrameSource(const PixelFormat& format);
157 ~FrameSource() = default;
158
159 void setHeight(unsigned height_) { height = height_; }
160
164 [[nodiscard]] virtual bool hasContiguousStorage() const {
165 return false;
166 }
167
168 template<std::unsigned_integral Pixel> void scaleLine(
169 std::span<const Pixel> in, std::span<Pixel> out) const;
170
171private:
174 const PixelFormat& pixelFormat;
175
178 unsigned height;
179
180 FieldType fieldType;
181};
182
183} // namespace openmsx
184
185#endif // FRAMESOURCE_HH
#define ALIGNAS_SSE
Definition: aligned.hh:24
Interface for getting lines from a video frame.
Definition: FrameSource.hh:20
virtual bool hasContiguousStorage() const
Returns true when two consecutive rows are also consecutive in memory.
Definition: FrameSource.hh:164
std::span< const Pixel, 640 > getLinePtr640_480(unsigned line, std::span< Pixel, 640 > buf) const
Get a pointer to a given line in this frame, the frame is scaled to 640x480 pixels.
Definition: FrameSource.cc:42
Pixel getLineColor(unsigned line) const
Get the (single) color of the given line.
Definition: FrameSource.hh:79
void scaleLine(std::span< const Pixel > in, std::span< Pixel > out) const
Definition: FrameSource.cc:81
virtual unsigned getLineWidth(unsigned line) const =0
Gets the number of display pixels on the given line.
FieldType getField() const
Gets the role this frame plays in interlacing.
Definition: FrameSource.hh:43
FrameSource(const PixelFormat &format)
Definition: FrameSource.cc:17
std::span< const Pixel > getLine(int line, std::span< Pixel > buf) const
Gets a pointer to the pixels of the given line number.
Definition: FrameSource.hh:96
std::span< const Pixel, 960 > getLinePtr960_720(unsigned line, std::span< Pixel, 960 > buf) const
Get a pointer to a given line in this frame, the frame is scaled to 960x720 pixels.
Definition: FrameSource.cc:57
void setHeight(unsigned height_)
Definition: FrameSource.hh:159
unsigned getWidth() const
Get the width of (all) lines in this frame.
Definition: FrameSource.hh:64
virtual const void * getLineInfo(unsigned line, unsigned &lineWidth, void *buf, unsigned bufWidth) const =0
Abstract implementation of getLinePtr().
void init(FieldType fieldType_)
(Re)initialize an existing FrameSource.
Definition: FrameSource.hh:39
std::span< const Pixel, 320 > getLinePtr320_240(unsigned line, std::span< Pixel, 320 > buf) const
Get a pointer to a given line in this frame, the frame is scaled to 320x240 pixels.
Definition: FrameSource.cc:23
unsigned getHeight() const
Gets the number of lines in this frame.
Definition: FrameSource.hh:49
FieldType
What role does this frame play in interlacing?
Definition: FrameSource.hh:24
@ FIELD_NONINTERLACED
Interlacing is off for this frame.
Definition: FrameSource.hh:27
@ FIELD_EVEN
Interlacing is on and this is an even frame.
Definition: FrameSource.hh:30
@ FIELD_ODD
Interlacing is on and this is an odd frame.
Definition: FrameSource.hh:33
const PixelFormat & getPixelFormat() const
Definition: FrameSource.hh:151
constexpr vecN< N, T > clamp(const vecN< N, T > &x, const vecN< N, T > &minVal, const vecN< N, T > &maxVal)
Definition: gl_vec.hh:293
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint32_t Pixel
constexpr auto xrange(T e)
Definition: xrange.hh:133