openMSX
HQ3xLiteScaler.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 "HQ3xLiteScaler.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 HQLite_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, EdgeHQLite 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  EdgeHQLite /*edgeOp*/) __restrict
36 {
37  unsigned c2, c4, c5, c6, c8, c9;
38  c2 = readPixel(in0[0]);
39  c5 = c6 = readPixel(in1[0]);
40  c8 = c9 = readPixel(in2[0]);
41 
42  unsigned pattern = 0;
43  if (c5 != c8) pattern |= 3 << 6;
44  if (c5 != c2) pattern |= 3 << 9;
45 
46  for (unsigned x = 0; x < srcWidth; ++x) {
47  c4 = c5; c5 = c6; c8 = c9;
48  if (x != srcWidth - 1) {
49  c6 = readPixel(in1[x + 1]);
50  c9 = readPixel(in2[x + 1]);
51  }
52 
53  pattern = (pattern >> 6) & 0x001F; // left overlap
54  // overlaps with left
55  //if (c8 != c4) pattern |= 1 << 0; // B - l: c5-c9 6
56  //if (c5 != c7) pattern |= 1 << 1; // B - l: c6-c8 7
57  //if (c5 != c4) pattern |= 1 << 2; // l: c5-c6 8
58  // overlaps with top and left
59  //if (c5 != c1) pattern |= 1 << 3; // l: c2-c6 9, t: c4-c8 0
60  //if (c4 != c2) pattern |= 1 << 4; // l: c5-c3 10, t: c5-c7 1
61  // non-overlapping pixels
62  if (c5 != c8) pattern |= 1 << 5; // B
63  if (c5 != c9) pattern |= 1 << 6; // BR
64  if (c6 != c8) pattern |= 1 << 7; // BR
65  if (c5 != c6) pattern |= 1 << 8; // R
66  // overlaps with top
67  //if (c2 != c6) pattern |= 1 << 9; // R - t: c5-c9 6
68  //if (c5 != c3) pattern |= 1 << 10; // R - t: c6-c8 7
69  //if (c5 != c2) pattern |= 1 << 11; // t: c5-c8 5
70  pattern |= ((edgeBuf[x] & (1 << 5) ) << 6) |
71  ((edgeBuf[x] & ((1 << 6) | (1 << 7))) << 3);
72  edgeBuf[x] = pattern;
73 
74  unsigned pixel0, pixel1, pixel2, pixel3, pixel4,
75  pixel5, pixel6, pixel7, pixel8;
76 
77 #include "HQ3xLiteScaler-1x1to3x3.nn"
78 
79  out0[3 * x + 0] = writePixel<Pixel>(pixel0);
80  out0[3 * x + 1] = writePixel<Pixel>(pixel1);
81  out0[3 * x + 2] = writePixel<Pixel>(pixel2);
82  out1[3 * x + 0] = writePixel<Pixel>(pixel3);
83  out1[3 * x + 1] = writePixel<Pixel>(pixel4);
84  out1[3 * x + 2] = writePixel<Pixel>(pixel5);
85  out2[3 * x + 0] = writePixel<Pixel>(pixel6);
86  out2[3 * x + 1] = writePixel<Pixel>(pixel7);
87  out2[3 * x + 2] = writePixel<Pixel>(pixel8);
88  }
89 }
90 
91 
92 template <class Pixel>
94  : Scaler3<Pixel>(pixelOps_)
95  , pixelOps(pixelOps_)
96 {
97 }
98 
99 template <class Pixel>
101  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
102  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
103 {
104  PolyScale<Pixel, Scale_2on3<Pixel>> postScale(pixelOps);
105  EdgeHQLite edgeOp;
106  doHQScale3<Pixel>(HQLite_1x1on3x3<Pixel>(), edgeOp, postScale,
107  src, srcStartY, srcEndY, srcWidth,
108  dst, dstStartY, dstEndY, (srcWidth * 9) / 2);
109 }
110 
111 template <class Pixel>
113  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
114  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
115 {
117  EdgeHQLite edgeOp;
118  doHQScale3<Pixel>(HQLite_1x1on3x3<Pixel>(), edgeOp, postScale,
119  src, srcStartY, srcEndY, srcWidth,
120  dst, dstStartY, dstEndY, srcWidth * 3);
121 }
122 
123 template <class Pixel>
125  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
126  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
127 {
128  PolyScale<Pixel, Scale_4on3<Pixel>> postScale(pixelOps);
129  EdgeHQLite edgeOp;
130  doHQScale3<Pixel>(HQLite_1x1on3x3<Pixel>(), edgeOp, postScale,
131  src, srcStartY, srcEndY, srcWidth,
132  dst, dstStartY, dstEndY, (srcWidth * 9) / 4);
133 }
134 
135 template <class Pixel>
137  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
138  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
139 {
140  PolyScale<Pixel, Scale_2on1<Pixel>> postScale(pixelOps);
141  EdgeHQLite edgeOp;
142  doHQScale3<Pixel>(HQLite_1x1on3x3<Pixel>(), edgeOp, postScale,
143  src, srcStartY, srcEndY, srcWidth,
144  dst, dstStartY, dstEndY, (srcWidth * 3) / 2);
145 }
146 
147 template <class Pixel>
149  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
150  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
151 {
152  PolyScale<Pixel, Scale_8on3<Pixel>> postScale(pixelOps);
153  EdgeHQLite edgeOp;
154  doHQScale3<Pixel>(HQLite_1x1on3x3<Pixel>(), edgeOp, postScale,
155  src, srcStartY, srcEndY, srcWidth,
156  dst, dstStartY, dstEndY, (srcWidth * 9) / 8);
157 }
158 
159 template <class Pixel>
161  unsigned srcStartY, unsigned srcEndY, unsigned srcWidth,
162  ScalerOutput<Pixel>& dst, unsigned dstStartY, unsigned dstEndY)
163 {
164  PolyScale<Pixel, Scale_4on1<Pixel>> postScale(pixelOps);
165  EdgeHQLite edgeOp;
166  doHQScale3<Pixel>(HQLite_1x1on3x3<Pixel>(), edgeOp, postScale,
167  src, srcStartY, srcEndY, srcWidth,
168  dst, dstStartY, dstEndY, (srcWidth * 3) / 4);
169 }
170 
171 // Force template instantiation.
172 #if HAVE_16BPP
173 template class HQ3xLiteScaler<uint16_t>;
174 #endif
175 #if HAVE_32BPP
176 template class HQ3xLiteScaler<uint32_t>;
177 #endif
178 
179 } // namespace openmsx
void scale2x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Polymorphic wrapper around another line scaler.
Definition: LineScalers.hh:310
uint32_t Pixel
Interface for getting lines from a video frame.
Definition: FrameSource.hh:14
void scale4x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale8x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale4x1to9x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
HQ3xLiteScaler(const PixelOperations< Pixel > &pixelOps)
void scale2x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void scale1x1to3x3(FrameSource &src, unsigned srcStartY, unsigned srcEndY, unsigned srcWidth, ScalerOutput< Pixel > &dst, unsigned dstStartY, unsigned dstEndY) override
void operator()(const Pixel *in0, const Pixel *in1, const Pixel *in2, Pixel *out0, Pixel *out1, Pixel *out2, unsigned srcWidth, unsigned *edgeBuf, EdgeHQLite edgeOp)
Base class for 3x scalers.
Definition: Scaler3.hh:11