openMSX
HQ3xScaler.cc
Go to the documentation of this file.
1 /*
2 Original code: Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )
3 openMSX adaptation by Wouter Vermaelen
4 
5 License: LGPL
6 
7 Visit the HiEnd3D site for info:
8  http://www.hiend3d.com/hq2x.html
9 */
10 
11 #include "HQ3xScaler.hh"
12 #include "HQCommon.hh"
13 #include "LineScalers.hh"
14 #include "unreachable.hh"
15 #include "build-info.hh"
16 #include <cstdint>
17 
18 namespace openmsx {
19 
20 template <typename Pixel> struct HQ_1x1on3x3
21 {
22  void operator()(const Pixel* in0, const Pixel* in1, const Pixel* in2,
23  Pixel* out0, Pixel* out1, Pixel* out2,
24  unsigned srcWidth, unsigned* edgeBuf, EdgeHQ edgeOp)
25  __restrict;
26 };
27 
28 template <typename Pixel>
30  const Pixel* __restrict in0, const Pixel* __restrict in1,
31  const Pixel* __restrict in2,
32  Pixel* __restrict out0, Pixel* __restrict out1,
33  Pixel* __restrict out2,
34  unsigned srcWidth, unsigned* __restrict edgeBuf,
35  EdgeHQ edgeOp) __restrict
36 {
37  unsigned c1, c2, c3, c4, c5, c6, c7, c8, c9;
38  c2 = c3 = readPixel(in0[0]);
39  c5 = c6 = readPixel(in1[0]);
40  c8 = c9 = readPixel(in2[0]);
41 
42  unsigned pattern = 0;
43  if (edgeOp(c5, c8)) pattern |= 3 << 6;
44  if (edgeOp(c5, c2)) pattern |= 3 << 9;
45 
46  for (unsigned x = 0; x < srcWidth; ++x) {
47  c1 = c2; c4 = c5; c7 = c8;
48  c2 = c3; c5 = c6; c8 = c9;
49  if (x != srcWidth - 1) {
50  c3 = readPixel(in0[x + 1]);
51  c6 = readPixel(in1[x + 1]);
52  c9 = readPixel(in2[x + 1]);
53  }
54 
55  pattern = (pattern >> 6) & 0x001F; // left overlap
56  // overlaps with left
57  //if (edgeOp(c8, c4)) pattern |= 1 << 0; // B - l: c5-c9 6
58  //if (edgeOp(c5, c7)) pattern |= 1 << 1; // B - l: c6-c8 7
59  //if (edgeOp(c5, c4)) pattern |= 1 << 2; // l: c5-c6 8
60  // overlaps with top and left
61  //if (edgeOp(c5, c1)) pattern |= 1 << 3; // l: c2-c6 9, t: c4-c8 0
62  //if (edgeOp(c4, c2)) pattern |= 1 << 4; // l: c5-c3 10, t: c5-c7 1
63  // non-overlapping pixels
64  if (edgeOp(c5, c8)) pattern |= 1 << 5; // B
65  if (edgeOp(c5, c9)) pattern |= 1 << 6; // BR
66  if (edgeOp(c6, c8)) pattern |= 1 << 7; // BR
67  if (edgeOp(c5, c6)) pattern |= 1 << 8; // R
68  // overlaps with top
69  //if (edgeOp(c2, c6)) pattern |= 1 << 9; // R - t: c5-c9 6
70  //if (edgeOp(c5, c3)) pattern |= 1 << 10; // R - t: c6-c8 7
71  //if (edgeOp(c5, c2)) pattern |= 1 << 11; // t: c5-c8 5
72  pattern |= ((edgeBuf[x] & (1 << 5) ) << 6) |
73  ((edgeBuf[x] & ((1 << 6) | (1 << 7))) << 3);
74  edgeBuf[x] = pattern;
75 
76  unsigned pixel0, pixel1, pixel2, pixel3, pixel4,
77  pixel5, pixel6, pixel7, pixel8;
78 
79 #include "HQ3xScaler-1x1to3x3.nn"
80 
81  out0[3 * x + 0] = writePixel<Pixel>(pixel0);
82  out0[3 * x + 1] = writePixel<Pixel>(pixel1);
83  out0[3 * x + 2] = writePixel<Pixel>(pixel2);
84  out1[3 * x + 0] = writePixel<Pixel>(pixel3);
85  out1[3 * x + 1] = writePixel<Pixel>(pixel4);
86  out1[3 * x + 2] = writePixel<Pixel>(pixel5);
87  out2[3 * x + 0] = writePixel<Pixel>(pixel6);
88  out2[3 * x + 1] = writePixel<Pixel>(pixel7);
89  out2[3 * x + 2] = writePixel<Pixel>(pixel8);
90  }
91 }
92 
93 
94 
95 template <class Pixel>
97  : Scaler3<Pixel>(pixelOps_)
98  , pixelOps(pixelOps_)
99 {
100 }
101 
102 template <class Pixel>
104  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
105  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
106 {
107  PolyScale<Pixel, Scale_2on3<Pixel>> postScale(pixelOps);
108  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
109  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
110  src, srcStartY, srcEndY, srcWidth,
111  dst, dstStartY, dstEndY, (srcWidth * 9) / 2);
112 }
113 
114 template <class Pixel>
116  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
117  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
118 {
120  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
121  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
122  src, srcStartY, srcEndY, srcWidth,
123  dst, dstStartY, dstEndY, srcWidth * 3);
124 }
125 
126 template <class Pixel>
128  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
129  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
130 {
131  PolyScale<Pixel, Scale_4on3<Pixel>> postScale(pixelOps);
132  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
133  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
134  src, srcStartY, srcEndY, srcWidth,
135  dst, dstStartY, dstEndY, (srcWidth * 9) / 4);
136 }
137 
138 template <class Pixel>
140  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
141  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
142 {
143  PolyScale<Pixel, Scale_2on1<Pixel>> postScale(pixelOps);
144  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
145  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
146  src, srcStartY, srcEndY, srcWidth,
147  dst, dstStartY, dstEndY, (srcWidth * 3) / 2);
148 }
149 
150 template <class Pixel>
152  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
153  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
154 {
155  PolyScale<Pixel, Scale_8on3<Pixel>> postScale(pixelOps);
156  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
157  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
158  src, srcStartY, srcEndY, srcWidth,
159  dst, dstStartY, dstEndY, (srcWidth * 9) / 8);
160 }
161 
162 template <class Pixel>
164  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
165  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
166 {
167  PolyScale<Pixel, Scale_4on1<Pixel>> postScale(pixelOps);
168  EdgeHQ edgeOp = createEdgeHQ(pixelOps);
169  doHQScale3<Pixel>(HQ_1x1on3x3<Pixel>(), edgeOp, postScale,
170  src, srcStartY, srcEndY, srcWidth,
171  dst, dstStartY, dstEndY, (srcWidth * 3) / 4);
172 }
173 
174 // Force template instantiation.
175 #if HAVE_16BPP
176 template class HQ3xScaler<uint16_t>;
177 #endif
178 #if HAVE_32BPP
179 template class HQ3xScaler<uint32_t>;
180 #endif
181 
182 } // namespace openmsx
openmsx::HQ3xScaler::scale8x1to9x3
void scale8x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ3xScaler.cc:151
openmsx::EdgeHQ
Definition: HQCommon.hh:42
openmsx::PixelOperations
Definition: PixelOperations.hh:142
openmsx::HQ3xScaler::scale4x1to9x3
void scale4x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ3xScaler.cc:127
openmsx::ScalerOutput
Definition: Scaler.hh:8
openmsx::Pixel
uint32_t Pixel
Definition: GLHQLiteScaler.cc:93
openmsx::HQ3xScaler::scale2x1to3x3
void scale2x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ3xScaler.cc:139
openmsx::HQ3xScaler
Runs the hq3x scaler algorithm.
Definition: HQ3xScaler.hh:12
openmsx::PolyScale
Polymorphic wrapper around another line scaler.
Definition: LineScalers.hh:311
build-info.hh
HQ3xScaler.hh
LineScalers.hh
openmsx::createEdgeHQ
EdgeHQ createEdgeHQ(const PixelOperations< Pixel > &pixelOps)
Definition: HQCommon.hh:84
openmsx::x
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:1377
openmsx::HQ3xScaler::scale2x1to9x3
void scale2x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ3xScaler.cc:103
openmsx::HQ3xScaler::scale1x1to3x3
void scale1x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ3xScaler.cc:115
openmsx::Scaler3
Base class for 3x scalers.
Definition: Scaler3.hh:11
openmsx::HQ3xScaler::HQ3xScaler
HQ3xScaler(const PixelOperations< Pixel > &pixelOps)
Definition: HQ3xScaler.cc:96
openmsx::FrameSource
Interface for getting lines from a video frame.
Definition: FrameSource.hh:13
openmsx::HQ_1x1on3x3
Definition: HQ3xScaler.cc:20
unreachable.hh
openmsx::HQ_1x1on3x3::operator()
void operator()(const Pixel *in0, const Pixel *in1, const Pixel *in2, Pixel *out0, Pixel *out1, Pixel *out2, unsigned srcWidth, unsigned *edgeBuf, EdgeHQ edgeOp)
Definition: HQ3xScaler.cc:29
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::HQ3xScaler::scale4x1to3x3
void scale4x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Definition: HQ3xScaler.cc:163
HQCommon.hh