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