openMSX
FrameSource.hh
Go to the documentation of this file.
1 #ifndef FRAMESOURCE_HH
2 #define FRAMESOURCE_HH
3 
4 #include "noncopyable.hh"
5 #include <algorithm>
6 #include <vector>
7 #include <cassert>
8 
9 struct SDL_PixelFormat;
10 
11 namespace openmsx {
12 
15 class FrameSource : private noncopyable
16 {
17 public:
20  enum FieldType {
30  };
31 
32  virtual ~FrameSource();
33 
37  void init(FieldType fieldType);
38 
41  FieldType getField() const {
42  return fieldType;
43  }
44 
47  unsigned getHeight() const {
48  return height;
49  }
50 
54  virtual unsigned getLineWidth(unsigned line) const = 0;
55 
62  unsigned getWidth() const {
63  unsigned height = getHeight();
64  assert(height > 0);
65  unsigned result = getLineWidth(0);
66  for (unsigned line = 1; line < height; ++line) {
67  assert(result == getLineWidth(line));
68  }
69  return result;
70  }
71 
74  template <typename Pixel>
75  inline const Pixel* getLinePtr(unsigned line) const {
76  unsigned dummy;
77  return reinterpret_cast<const Pixel*>(getLineInfo(line, dummy));
78  }
79 
86  template <typename Pixel>
87  inline const Pixel* getLinePtr(int line, unsigned width) const
88  {
89  line = std::min<unsigned>(std::max(0, line), getHeight() - 1);
90  unsigned internalWidth;
91  auto internalData = reinterpret_cast<const Pixel*>(
92  getLineInfo(line, internalWidth));
93  if (internalWidth == width) {
94  return internalData;
95  } else {
96  // slow path, non-inlined
97  return scaleLine(internalData, internalWidth, width);
98  }
99  }
100 
106  template <typename Pixel>
107  inline const Pixel* getMultiLinePtr(
108  int line, unsigned numLines, unsigned& actualLines,
109  unsigned width) const
110  {
111  actualLines = 1;
112  int height = getHeight();
113  if ((line < 0) || (height <= line)) {
114  return getLinePtr<Pixel>(line, width);
115  }
116  unsigned internalWidth;
117  auto internalData = reinterpret_cast<const Pixel*>(
118  getLineInfo(line, internalWidth));
119  if (internalWidth != width) {
120  return scaleLine(internalData, internalWidth, width);
121  }
122  if (!hasContiguousStorage()) {
123  return internalData;
124  }
125  while (--numLines) {
126  ++line;
127  if ((line == height) || (getLineWidth(line) != width)) {
128  break;
129  }
130  ++actualLines;
131  }
132  return internalData;
133  }
134 
142  template <typename Pixel>
143  const Pixel* getLinePtr320_240(unsigned line) const;
144 
149  template <typename Pixel>
150  const Pixel* getLinePtr640_480(unsigned line) const;
151 
156  template <typename Pixel>
157  const Pixel* getLinePtr960_720(unsigned line) const;
158 
165  virtual unsigned getRowLength() const {
166  return 0;
167  }
168 
171  void freeLineBuffers() const;
172 
173  const SDL_PixelFormat& getSDLPixelFormat() const {
174  return pixelFormat;
175  }
176 
177  // Used by SuperImposedFrame.
178  // TODO refactor
179  void* getTempBuffer() const;
180 
181 protected:
182  explicit FrameSource(const SDL_PixelFormat& format);
183 
184  void setHeight(unsigned height);
185 
190  virtual const void* getLineInfo(unsigned line, unsigned& width) const = 0;
191 
195  virtual bool hasContiguousStorage() const {
196  return false;
197  }
198 
199  // TODO: I don't understand why I need to declare a subclass as friend
200  // to give it access to a protected method, but without this
201  // GCC 3.3.5-pre will not compile it.
202  friend class DeinterlacedFrame;
203  friend class DoubledFrame;
204 
205 private:
206  template <typename Pixel> const Pixel* scaleLine(
207  const Pixel* in, unsigned inWidth, unsigned outWidth) const;
208  template <typename Pixel> const Pixel* blendLines(
209  const Pixel* line1, const Pixel* line2, unsigned width) const;
210 
213  const SDL_PixelFormat& pixelFormat;
214 
217  unsigned height;
218 
219  FieldType fieldType;
220  mutable std::vector<void*> tempBuffers;
221  mutable unsigned tempCounter;
222 };
223 
224 } // namespace openmsx
225 
226 #endif // FRAMESOURCE_HH