openMSX
StretchScalerOutput.cc
Go to the documentation of this file.
1 #include "StretchScalerOutput.hh"
2 #include "DirectScalerOutput.hh"
3 #include "LineScalers.hh"
4 #include "PixelOperations.hh"
5 #include "MemoryOps.hh"
6 #include "build-info.hh"
7 #include <cstdint>
8 #include <memory>
9 #include <vector>
10 
11 using std::unique_ptr;
12 
13 namespace openmsx {
14 
15 template<typename Pixel>
17 {
18 public:
21  ~StretchScalerOutputBase() override;
22 
23  unsigned getWidth() const override;
24  unsigned getHeight() const override;
25  Pixel* acquireLine(unsigned y) override;
26  void fillLine (unsigned y, Pixel color) override;
27 
28 protected:
29  Pixel* releasePre(unsigned y, Pixel* buf);
30  void releasePost(unsigned y, Pixel* dstLine);
31 
33 
34 private:
35  unique_ptr<ScalerOutput<Pixel>> output;
36  std::vector<Pixel*> pool;
37 };
38 
39 template<typename Pixel>
41 {
42 public:
43  StretchScalerOutput(unique_ptr<ScalerOutput<Pixel>> output,
45  unsigned inWidth);
46  void releaseLine(unsigned y, Pixel* buf) override;
47 
48 private:
49  unsigned inWidth;
50 };
51 
52 template<typename Pixel, unsigned IN_WIDTH, typename SCALE>
54 {
55 public:
56  StretchScalerOutputN(unique_ptr<ScalerOutput<Pixel>> output,
58  void releaseLine(unsigned y, Pixel* buf) override;
59 };
60 
61 template<typename Pixel>
63  : public StretchScalerOutputN<Pixel, 256, Scale_4on5<Pixel>>
64 {
65 public:
68 };
69 
70 template<typename Pixel>
72  : public StretchScalerOutputN<Pixel, 272, Scale_17on20<Pixel>>
73 {
74 public:
77 };
78 
79 template<typename Pixel>
81  : public StretchScalerOutputN<Pixel, 280, Scale_7on8<Pixel>>
82 {
83 public:
86 };
87 
88 template<typename Pixel>
90  : public StretchScalerOutputN<Pixel, 288, Scale_9on10<Pixel>>
91 {
92 public:
95 };
96 
97 
98 // class StretchScalerOutputBase
99 
100 template<typename Pixel>
102  unique_ptr<ScalerOutput<Pixel>> output_,
103  PixelOperations<Pixel> pixelOps_)
104  : pixelOps(std::move(pixelOps_))
105  , output(std::move(output_))
106 {
107 }
108 
109 template<typename Pixel>
111 {
112  for (auto& p : pool) {
114  }
115 }
116 
117 template<typename Pixel>
119 {
120  return output->getWidth();
121 }
122 
123 template<typename Pixel>
125 {
126  return output->getHeight();
127 }
128 
129 template<typename Pixel>
131 {
132  if (!pool.empty()) {
133  Pixel* buf = pool.back();
134  pool.pop_back();
135  return buf;
136  } else {
137  unsigned size = sizeof(Pixel) * output->getWidth();
138  return static_cast<Pixel*>(MemoryOps::mallocAligned(64, size));
139  }
140 }
141 
142 template<typename Pixel>
144 {
145  pool.push_back(buf);
146  return output->acquireLine(y);
147 }
148 
149 template<typename Pixel>
151 {
152  output->releaseLine(y, dstLine);
153 }
154 
155 template<typename Pixel>
157 {
158  Pixel* dstLine = output->acquireLine(y);
160  memset(dstLine, output->getWidth(), color);
161  output->releaseLine(y, dstLine);
162 }
163 
164 
165 // class StretchScalerOutput
166 
167 template<typename Pixel>
169  unique_ptr<ScalerOutput<Pixel>> output_,
170  PixelOperations<Pixel> pixelOps_,
171  unsigned inWidth_)
172  : StretchScalerOutputBase<Pixel>(std::move(output_), std::move(pixelOps_))
173  , inWidth(inWidth_)
174 {
175 }
176 
177 template<typename Pixel>
179 {
180  Pixel* dstLine = this->releasePre(y, buf);
181 
182  unsigned dstWidth = StretchScalerOutputBase<Pixel>::getWidth();
183  unsigned srcWidth = (dstWidth / 320) * inWidth;
184  unsigned srcOffset = (dstWidth - srcWidth) / 2;
185  ZoomLine<Pixel> zoom(this->pixelOps);
186  zoom(buf + srcOffset, srcWidth, dstLine, dstWidth);
187 
188  this->releasePost(y, dstLine);
189 }
190 
191 
192 // class StretchScalerOutputN
193 
194 template<typename Pixel, unsigned IN_WIDTH, typename SCALE>
196  unique_ptr<ScalerOutput<Pixel>> output_,
197  PixelOperations<Pixel> pixelOps_)
198  : StretchScalerOutputBase<Pixel>(std::move(output_), std::move(pixelOps_))
199 {
200 }
201 
202 template<typename Pixel, unsigned IN_WIDTH, typename SCALE>
204 {
205  Pixel* dstLine = this->releasePre(y, buf);
206 
207  unsigned dstWidth = StretchScalerOutputBase<Pixel>::getWidth();
208  unsigned srcWidth = (dstWidth / 320) * IN_WIDTH;
209  unsigned srcOffset = (dstWidth - srcWidth) / 2;
210  SCALE scale(this->pixelOps);
211  scale(buf + srcOffset, dstLine, dstWidth);
212 
213  this->releasePost(y, dstLine);
214 }
215 
216 
217 // class StretchScalerOutput256
218 
219 template<typename Pixel>
221  unique_ptr<ScalerOutput<Pixel>> output_,
222  PixelOperations<Pixel> pixelOps_)
224  std::move(output_), std::move(pixelOps_))
225 {
226 }
227 
228 
229 // class StretchScalerOutput272
230 
231 template<typename Pixel>
233  unique_ptr<ScalerOutput<Pixel>> output_,
234  PixelOperations<Pixel> pixelOps_)
236  std::move(output_), std::move(pixelOps_))
237 {
238 }
239 
240 
241 // class StretchScalerOutput280
242 
243 template<typename Pixel>
245  unique_ptr<ScalerOutput<Pixel>> output_,
246  PixelOperations<Pixel> pixelOps_)
248  std::move(output_), std::move(pixelOps_))
249 {
250 }
251 
252 
253 // class StretchScalerOutput288
254 
255 template<typename Pixel>
257  unique_ptr<ScalerOutput<Pixel>> output_,
258  PixelOperations<Pixel> pixelOps_)
260  std::move(output_), std::move(pixelOps_))
261 {
262 }
263 
264 
265 // class StretchScalerOutputFactory
266 
267 template<typename Pixel>
268 unique_ptr<ScalerOutput<Pixel>> StretchScalerOutputFactory<Pixel>::create(
269  OutputSurface& output,
271  unsigned inWidth)
272 {
273  auto direct = std::make_unique<DirectScalerOutput<Pixel>>(output);
274  switch (inWidth) {
275  case 320:
276  return std::move(direct);
277  case 288:
278  return std::make_unique<StretchScalerOutput288<Pixel>>(
279  std::move(direct), std::move(pixelOps));
280  case 280:
281  return std::make_unique<StretchScalerOutput280<Pixel>>(
282  std::move(direct), std::move(pixelOps));
283  case 272:
284  return std::make_unique<StretchScalerOutput272<Pixel>>(
285  std::move(direct), std::move(pixelOps));
286  case 256:
287  return std::make_unique<StretchScalerOutput256<Pixel>>(
288  std::move(direct), std::move(pixelOps));
289  default:
290  return std::make_unique<StretchScalerOutput<Pixel>>(
291  std::move(direct), std::move(pixelOps), inWidth);
292  }
293 }
294 
295 // Force template instantiation.
296 #if HAVE_16BPP
298 #endif
299 #if HAVE_32BPP
301 #endif
302 
303 } // namespace openmsx
void releasePost(unsigned y, Pixel *dstLine)
void releaseLine(unsigned y, Pixel *buf) override
StretchScalerOutput288(unique_ptr< ScalerOutput< Pixel >> output, PixelOperations< Pixel > pixelOps)
Pixel * acquireLine(unsigned y) override
StretchScalerOutputN(unique_ptr< ScalerOutput< Pixel >> output, PixelOperations< Pixel > pixelOps)
StretchScalerOutput280(unique_ptr< ScalerOutput< Pixel >> output, PixelOperations< Pixel > pixelOps)
StretchScalerOutput272(unique_ptr< ScalerOutput< Pixel >> output, PixelOperations< Pixel > pixelOps)
Stretch (or zoom) a given input line to a wider output line.
Definition: LineScalers.hh:237
void freeAligned(void *)
Definition: MemoryOps.cc:282
StretchScalerOutputBase(unique_ptr< ScalerOutput< Pixel >> output, PixelOperations< Pixel > pixelOps)
STL namespace.
A frame buffer where pixels can be written to.
uint32_t Pixel
mat4 scale(const vec3 &xyz)
Definition: gl_transform.hh:19
Pixel * releasePre(unsigned y, Pixel *buf)
void * mallocAligned(size_t alignment, size_t size)
Definition: MemoryOps.cc:252
void fillLine(unsigned y, Pixel color) override
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
virtual void releaseLine(unsigned y, Pixel *buf)=0
const PixelOperations< Pixel > pixelOps
static std::unique_ptr< ScalerOutput< Pixel > > create(OutputSurface &output, PixelOperations< Pixel > pixelOps, unsigned inWidth)
unsigned getWidth() const override
unsigned getHeight() const override
constexpr auto size(const C &c) -> decltype(c.size())
Definition: span.hh:62
StretchScalerOutput(unique_ptr< ScalerOutput< Pixel >> output, PixelOperations< Pixel > pixelOps, unsigned inWidth)