openMSX
HQ2xScaler.cc
Go to the documentation of this file.
1 /*
2 Original code: Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )
3 openMSX adaptation by Maarten ter Huurne
4 
5 License: LGPL
6 
7 Visit the HiEnd3D site for info:
8  http://www.hiend3d.com/hq2x.html
9 */
10 
11 #include "HQ2xScaler.hh"
12 #include "HQCommon.hh"
13 #include "LineScalers.hh"
14 #include "unreachable.hh"
15 #include "xrange.hh"
16 #include "build-info.hh"
17 #include <cstdint>
18 
19 namespace openmsx {
20 
21 template<typename Pixel> struct HQ_1x1on2x2
22 {
23  void operator()(const Pixel* in0, const Pixel* in1, const Pixel* in2,
24  Pixel* out0, Pixel* out1, unsigned srcWidth,
25  unsigned* edgeBuf, EdgeHQ edgeOp) __restrict;
26 };
27 
28 template<typename Pixel> struct HQ_1x1on1x2
29 {
30  void operator()(const Pixel* in0, const Pixel* in1, const Pixel* in2,
31  Pixel* out0, Pixel* out1, unsigned srcWidth,
32  unsigned* edgeBuf, EdgeHQ edgeOp) __restrict;
33 };
34 
35 template<typename Pixel>
37  const Pixel* __restrict in0, const Pixel* __restrict in1,
38  const Pixel* __restrict in2,
39  Pixel* __restrict out0, Pixel* __restrict out1,
40  unsigned srcWidth, unsigned* __restrict edgeBuf,
41  EdgeHQ edgeOp) __restrict
42 {
43  unsigned c2 = readPixel(in0[0]); unsigned c3 = c2;
44  unsigned c5 = readPixel(in1[0]); unsigned c6 = c5;
45  unsigned c8 = readPixel(in2[0]); unsigned c9 = c8;
46 
47  unsigned pattern = 0;
48  if (edgeOp(c5, c8)) pattern |= 3 << 6;
49  if (edgeOp(c5, c2)) pattern |= 3 << 9;
50 
51  for (auto x : xrange(srcWidth)) {
52  unsigned c1 = c2;
53  unsigned c4 = c5;
54  unsigned c7 = c8;
55  c2 = c3;
56  c5 = c6;
57  c8 = c9;
58  if (x != srcWidth - 1) {
59  c3 = readPixel(in0[x + 1]);
60  c6 = readPixel(in1[x + 1]);
61  c9 = readPixel(in2[x + 1]);
62  }
63 
64  pattern = (pattern >> 6) & 0x001F; // left overlap
65  // overlaps with left
66  //if (edgeOp(c8, c4)) pattern |= 1 << 0; // B - l: c5-c9 6
67  //if (edgeOp(c5, c7)) pattern |= 1 << 1; // B - l: c6-c8 7
68  //if (edgeOp(c5, c4)) pattern |= 1 << 2; // l: c5-c6 8
69  // overlaps with top and left
70  //if (edgeOp(c5, c1)) pattern |= 1 << 3; // l: c2-c6 9, t: c4-c8 0
71  //if (edgeOp(c4, c2)) pattern |= 1 << 4; // l: c5-c3 10, t: c5-c7 1
72  // non-overlapping pixels
73  if (edgeOp(c5, c8)) pattern |= 1 << 5; // B
74  if (edgeOp(c5, c9)) pattern |= 1 << 6; // BR
75  if (edgeOp(c6, c8)) pattern |= 1 << 7; // BR
76  if (edgeOp(c5, c6)) pattern |= 1 << 8; // R
77  // overlaps with top
78  //if (edgeOp(c2, c6)) pattern |= 1 << 9; // R - t: c5-c9 6
79  //if (edgeOp(c5, c3)) pattern |= 1 << 10; // R - t: c6-c8 7
80  //if (edgeOp(c5, c2)) pattern |= 1 << 11; // t: c5-c8 5
81  pattern |= ((edgeBuf[x] & (1 << 5) ) << 6) |
82  ((edgeBuf[x] & ((1 << 6) | (1 << 7))) << 3);
83  edgeBuf[x] = pattern;
84 
85  unsigned pixel0, pixel1, pixel2, pixel3;
86 
87 #include "HQ2xScaler-1x1to2x2.nn"
88 
89  out0[2 * x + 0] = writePixel<Pixel>(pixel0);
90  out0[2 * x + 1] = writePixel<Pixel>(pixel1);
91  out1[2 * x + 0] = writePixel<Pixel>(pixel2);
92  out1[2 * x + 1] = writePixel<Pixel>(pixel3);
93  }
94 }
95 
96 template<typename Pixel>
98  const Pixel* __restrict in0, const Pixel* __restrict in1,
99  const Pixel* __restrict in2,
100  Pixel* __restrict out0, Pixel* __restrict out1,
101  unsigned srcWidth, unsigned* __restrict edgeBuf,
102  EdgeHQ edgeOp) __restrict
103 {
104  // +---+---+---+
105  // | 1 | 2 | 3 |
106  // +---+---+---+
107  // | 4 | 5 | 6 |
108  // +---+---+---+
109  // | 7 | 8 | 9 |
110  // +---+---+---+
111 
112  unsigned c2 = readPixel(in0[0]); unsigned c3 = c2;
113  unsigned c5 = readPixel(in1[0]); unsigned c6 = c5;
114  unsigned c8 = readPixel(in2[0]); unsigned c9 = c8;
115 
116  unsigned pattern = 0;
117  if (edgeOp(c5, c8)) pattern |= 3 << 6;
118  if (edgeOp(c5, c2)) pattern |= 3 << 9;
119 
120  for (auto x : xrange(srcWidth)) {
121  unsigned c1 = c2;
122  unsigned c4 = c5;
123  unsigned c7 = c8;
124  c2 = c3;
125  c5 = c6;
126  c8 = c9;
127  if (x != srcWidth - 1) {
128  c3 = readPixel(in0[x + 1]);
129  c6 = readPixel(in1[x + 1]);
130  c9 = readPixel(in2[x + 1]);
131  }
132 
133  pattern = (pattern >> 6) & 0x001F; // left overlap
134  // overlaps with left
135  //if (edgeOp(c8, c4)) pattern |= 1 << 0; // B - l: c5-c9 6
136  //if (edgeOp(c5, c7)) pattern |= 1 << 1; // B - l: c6-c8 7
137  //if (edgeOp(c5, c4)) pattern |= 1 << 2; // l: c5-c6 8
138  // overlaps with top and left
139  //if (edgeOp(c5, c1)) pattern |= 1 << 3; // l: c2-c6 9, t: c4-c8 0
140  //if (edgeOp(c4, c2)) pattern |= 1 << 4; // l: c5-c3 10, t: c5-c7 1
141  // non-overlapping pixels
142  if (edgeOp(c5, c8)) pattern |= 1 << 5; // B
143  if (edgeOp(c5, c9)) pattern |= 1 << 6; // BR
144  if (edgeOp(c6, c8)) pattern |= 1 << 7; // BR
145  if (edgeOp(c5, c6)) pattern |= 1 << 8; // R
146  // overlaps with top
147  //if (edgeOp(c2, c6)) pattern |= 1 << 9; // R - t: c5-c9 6
148  //if (edgeOp(c5, c3)) pattern |= 1 << 10; // R - t: c6-c8 7
149  //if (edgeOp(c5, c2)) pattern |= 1 << 11; // t: c5-c8 5
150  pattern |= ((edgeBuf[x] & (1 << 5) ) << 6) |
151  ((edgeBuf[x] & ((1 << 6) | (1 << 7))) << 3);
152  edgeBuf[x] = pattern;
153 
154  unsigned pixel0, pixel1;
155 
156 #include "HQ2xScaler-1x1to1x2.nn"
157 
158  out0[x] = writePixel<Pixel>(pixel0);
159  out1[x] = writePixel<Pixel>(pixel1);
160  }
161 }
162 
163 
164 
165 template<typename Pixel>
167  : Scaler2<Pixel>(pixelOps_)
168  , pixelOps(pixelOps_)
169 {
170 }
171 
172 template<typename Pixel>
174  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
175  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
176 {
177  PolyScale<Pixel, Scale_2on3<Pixel>> postScale(pixelOps);
178  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
179  doHQScale2<Pixel>(HQ_1x1on2x2<Pixel>(), edgeOp, postScale,
180  src, srcStartY, srcEndY, srcWidth,
181  dst, dstStartY, dstEndY, srcWidth * 3);
182 }
183 
184 template<typename Pixel>
186  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
187  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
188 {
190  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
191  doHQScale2<Pixel>(HQ_1x1on2x2<Pixel>(), edgeOp, postScale,
192  src, srcStartY, srcEndY, srcWidth,
193  dst, dstStartY, dstEndY, srcWidth * 2);
194 }
195 
196 template<typename Pixel>
198  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
199  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
200 {
201  PolyScale<Pixel, Scale_4on3<Pixel>> postScale(pixelOps);
202  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
203  doHQScale2<Pixel>(HQ_1x1on2x2<Pixel>(), edgeOp, postScale,
204  src, srcStartY, srcEndY, srcWidth,
205  dst, dstStartY, dstEndY, (srcWidth * 3) / 2);
206 }
207 
208 template<typename Pixel>
210  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
211  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
212 {
214  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
215  doHQScale2<Pixel>(HQ_1x1on1x2<Pixel>(), edgeOp, postScale,
216  src, srcStartY, srcEndY, srcWidth,
217  dst, dstStartY, dstEndY, srcWidth);
218 }
219 
220 template<typename Pixel>
222  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
223  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
224 {
225  PolyScale<Pixel, Scale_4on3<Pixel>> postScale(pixelOps);
226  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
227  doHQScale2<Pixel>(HQ_1x1on1x2<Pixel>(), edgeOp, postScale,
228  src, srcStartY, srcEndY, srcWidth,
229  dst, dstStartY, dstEndY, (srcWidth * 3) / 4);
230 }
231 
232 template<typename Pixel>
234  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
235  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
236 {
237  PolyScale<Pixel, Scale_2on1<Pixel>> postScale(pixelOps);
238  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
239  doHQScale2<Pixel>(HQ_1x1on1x2<Pixel>(), edgeOp, postScale,
240  src, srcStartY, srcEndY, srcWidth,
241  dst, dstStartY, dstEndY, srcWidth / 2);
242 }
243 
244 // Force template instantiation.
245 #if HAVE_16BPP
246 template class HQ2xScaler<uint16_t>;
247 #endif
248 #if HAVE_32BPP
249 template class HQ2xScaler<uint32_t>;
250 #endif
251 
252 } // namespace openmsx
Interface for getting lines from a video frame.
Definition: FrameSource.hh:15
Runs the hq2x scaler algorithm.
Definition: HQ2xScaler.hh:13
void scale1x1to3x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ2xScaler.cc:173
void scale1x1to2x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ2xScaler.cc:185
HQ2xScaler(const PixelOperations< Pixel > &pixelOps)
Definition: HQ2xScaler.cc:166
void scale2x1to3x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ2xScaler.cc:197
void scale1x1to1x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ2xScaler.cc:209
void scale4x1to3x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ2xScaler.cc:221
void scale2x1to1x2(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ2xScaler.cc:233
Polymorphic wrapper around another line scaler.
Definition: LineScalers.hh:313
Base class for 2x scalers.
Definition: Scaler2.hh:12
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint32_t Pixel
EdgeHQ createEdgeHQ(const PixelOperations< Pixel > &pixelOps)
Definition: HQCommon.hh:86
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:124
uint32_t readPixel(Pixel p)
Definition: HQCommon.hh:19
void operator()(const Pixel *in0, const Pixel *in1, const Pixel *in2, Pixel *out0, Pixel *out1, unsigned srcWidth, unsigned *edgeBuf, EdgeHQ edgeOp)
Definition: HQ2xScaler.cc:97
void operator()(const Pixel *in0, const Pixel *in1, const Pixel *in2, Pixel *out0, Pixel *out1, unsigned srcWidth, unsigned *edgeBuf, EdgeHQ edgeOp)
Definition: HQ2xScaler.cc:36
constexpr auto xrange(T e)
Definition: xrange.hh:155