openMSX
HQ2xScaler.cc
Go to the documentation of this file.
1/*
2Original code: Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )
3openMSX adaptation by Maarten ter Huurne
4
5License: LGPL
6
7Visit 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
19namespace openmsx {
20
21template<std::unsigned_integral 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
28template<std::unsigned_integral 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
35template<std::unsigned_integral 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
96template<std::unsigned_integral 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
165template<std::unsigned_integral Pixel>
167 : Scaler2<Pixel>(pixelOps_)
168 , pixelOps(pixelOps_)
169{
170}
171
172template<std::unsigned_integral 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
184template<std::unsigned_integral 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
196template<std::unsigned_integral 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
208template<std::unsigned_integral 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
220template<std::unsigned_integral 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
232template<std::unsigned_integral 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
246template class HQ2xScaler<uint16_t>;
247#endif
248#if HAVE_32BPP
249template class HQ2xScaler<uint32_t>;
250#endif
251
252} // namespace openmsx
Interface for getting lines from a video frame.
Definition: FrameSource.hh:17
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:85
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:127
uint32_t readPixel(Pixel p)
Definition: HQCommon.hh:18
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:133